I’m creating a Quiz App. This is the Quiz Page Code. Quiz DB Document contains a QuizQuestions
Array which has question ids. Then I fetch specific question from MCQ/Question DB. Fetching MCQ takes time and when I console.log
fetched data. First and second time data in undefined then its viewable. Due to this I’m unable to display it as it cause TypeError: Cannot read properties of undefined mcqOptions
How can I fix this?
`
import React, { useEffect, useState } from "react"; import shuffleMcq from "../components/shuffleMcq"; const QuizTakePage = ({ match }) => { const reqUrl = match.params.path; //Getting Quiz ID From URL const [quizInfo, setQuizInfo] = useState({ "q_title":"", "q_seo_description":"", "q_questions":[], "q_tags":[], "m_subject":"", }) //const fetchQuizData = fetch(); useEffect(() => { const fetchQuizData = async () => { const reqApiUrl = '/quiz/api/qid/'+reqUrl; const fetchedApiResult = await fetch(reqApiUrl); const resultJson = await fetchedApiResult.json(); setQuizInfo(resultJson); } fetchQuizData(); }, []); // Quiz Data START const quizTitle = quizInfo.q_title; const quizDesc = quizInfo.q_seo_description; const quizQuestions = quizInfo.q_questions; // Quiz Data END // MCQ Data START const [currentQuestion, setCurrentQuestion] = useState(0); const requestedQuestion = quizQuestions[currentQuestion]; const [mcqInfo, setMcqInfo] = useState({ "m_title":"", "m_question":"", "m_alternatives":[], "m_language":"", }) useEffect(() => { const fetchApiResponse = async () => { const reqApiUrl = '/mcq/api/mid/'+requestedQuestion; const fetchedApiResult = await fetch(reqApiUrl); const resultJson = await fetchedApiResult.json(); setMcqInfo(resultJson); } fetchApiResponse(); }, [requestedQuestion]); //const mcqLanguage = mcqInfo.m_language; const mcqQuestion = mcqInfo.m_question; const mcqOptions = mcqInfo.m_alternatives; console.log(mcqOptions); return ( <> <h1>{quizTitle}</h1> <p>{quizDesc}</p> </> ); }; export default QuizTakePage;
Advertisement
Answer
The reason you’re getting undefined
for the first and second time is due to the fact that useEffect
would’ve not been executed by then. useEffect
runs when the component is rendered and mounted for the first time, and then subsequent executions are made when there is a change in dependency array (If there are any dependencies).
You could get rid of the error by rendering the dynamic content conditionally, i.e, displaying it when the data has been fetched.
return ( <> <h1>{quizTitle.length>0 ? quizTitle : "Loading Question"}</h1> <p>{quizDesc.length>0 ? quizDesc: "Loading Description"}</p> <ul> {mcqOptions && mcqOptions.length>0 && mcqOptions.map(option=>{ return(<li key={Math.random()}>{option}</li>) //Using Math.random() for key to ensure all the mapped items have an unique key } } </ul> </> );
Alternatively, if your mcqOptions
is an array of objects
you can map
it accordingly, for instance, something like this,
<ul> {mcqOptions && mcqOptions.length>0 && mcqOptions.map(mcqOption=>{ return(<li key={mcqOption.id}>{mcqOption.text}</li>) //Use the properties accordingly, this is an example only. } } </ul>