Home > front end >  Why am i getting undefined in my console, when i try to subscribe and use my context using typescrip
Why am i getting undefined in my console, when i try to subscribe and use my context using typescrip

Time:07-28

When trying to create a simple quiz app without the need to prop drilling I've stumbled upon an issue while trying to integrate context into the project. The issue is that when subscribing to my context as shown below and console. logging 'name', I get the value of undefined. What am I missing in order to get my name(stored in a state in my context) logged instead of getting undefined?

My context

import React, { createContext, Dispatch, SetStateAction, useContext, useState } from 'react';

export interface IUserContextType {
  name: string;
  test: string;
  setName: Dispatch<SetStateAction<string>>;
  setTest: Dispatch<SetStateAction<string>>;
}

type IQuizContextProvidorProps = {
  children: React.ReactNode;
};

export const QuizContext = createContext({} as IUserContextType);

export const useQuizContext = () => useContext(QuizContext);

const QuizContexProvider = ({ children }: IQuizContextProvidorProps) => {
  const [name, setName] = useState('Marvin');
  const [test, setTest] = useState('This is a test');
  const values = { name, test, setName, setTest };

  return <QuizContext.Provider value={values}>{children}</QuizContext.Provider>;
};

export default QuizContexProvider;

My App

import { useState } from 'react';
import './App.css';
import quizApi from './utils/quiz.json';
import { IQuiz, IQuizAnswers } from './model/IQuiz';
import { Button, LinearProgress, Paper, styled, Typography } from '@mui/material';
import { Box } from '@mui/system';
import QuizContexProvider, { useQuizContext } from './utils/QuizContex';

const QuizContainer = styled(Box)(({ theme }) => ({
  '.correct': {
    backgroundColor: 'darkseagreen',
  },
  '.linearProgress': {
    height: '1rem',
  },
}));

function App() {
  const { name, test } = useQuizContext();
  console.log('name', name);

  function shuffle(array: Array<any>) {
    return array.sort(() => Math.random() - 0.5);
  }

  const quiz: Array<IQuiz> = shuffle(quizApi);

  const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
  const [progress, setProgress] = useState(0);
  const [viewQuiz, setViewQuiz] = useState(true);
  const [quizScore, setQuizScore] = useState(0);

  const inkrementWith = 100 / quiz.length;

  const handleProgress = () => {
    setProgress(progress   inkrementWith);
  };

  const handleAnswer = (answers: IQuizAnswers) => {
    const nextQuestion = currentQuestionIndex   1;
    handleProgress();

    if (nextQuestion < quiz.length) {
      setCurrentQuestionIndex(nextQuestion);
    } else {
      setViewQuiz(false);
    }

    if (answers.isTrue === true) {
      setQuizScore(quizScore   1);
    }
  };

  const handleReset = () => {
    setCurrentQuestionIndex(0);
    setProgress(0);
    setQuizScore(0);
    setViewQuiz(true);
  };
  return (
    <QuizContexProvider>
      <QuizContainer className='App'>
        <Box component='header' className='App-header'>
          {viewQuiz ? (
            <>
              <Box sx={{ width: '50%' }}>
                <LinearProgress className='linearProgress' variant='determinate' color='success' value={progress} />
              </Box>

              {quiz.map(
                (question, index) =>
                  index === currentQuestionIndex && (
                    <Box key={index}>
                      <Box>{question.questionLabel}</Box>
                      <Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem', margin: '1rem' }}>
                        {shuffle(question.answerOptions).map((answers, index) => (
                          <Paper
                            key={index}
                            onClick={() => {
                              return handleAnswer(answers);
                            }}
                            component='button'
                          >
                            {answers.answerLabel}
                          </Paper>
                        ))}
                      </Box>
                    </Box>
                  )
              )}
            </>
          ) : (
            <Paper>
              <Typography component='h1' variant='h3'>
                Quiz results
              </Typography>
              <Typography component='h2' variant='subtitle1'>
                Quiz results
              </Typography>

              <Typography component='h1' variant='h1' sx={{ fontWeight: 700 }}>
                {quizScore} / {quiz.length}
              </Typography>
              <Button variant='contained' onClick={handleReset} sx={{ margin: '1rem 0rem' }}>
                Reset quiz
              </Button>
            </Paper>
          )}
        </Box>
      </QuizContainer>
    </QuizContexProvider>
  );
}

export default App;

CodePudding user response:

Any component that wish to use context value, should be wrapped inside the provider. Your <App /> component is using context value, so it should be:

<QuizContexProvider>
  <App />
</QuizContexProvider>

You can put the provider in Index.ts file.

  • Related