简体   繁体   中英

Uncaught TypeError: Cannot read properties of undefined (reading 'question'). This is after using useState() to set the data from a GET request

I am making a simple GET request and want to make that data more accessible using useState() but it seems as though this error is caused by accessing an property that does not exist due to useState not updating it?

Even though I have made GET requests very similar to this, it is the first time I am using useLocation(). I'm not sure if that has anything to do with the problem or it has something to do with useState().

Any response is much appreciated

    const getQuiz = async () => {
        try{
            // These values were passed by the difficulty Component
            const categoryName = location.state?.name
            const difficulty = location.state?.difficulty

            // This makes a get request to get data for the quiz
            let response = await axios.get(`https://the-trivia-api.com/api/questions?categories=${categoryName}&limit=10&difficulty=${difficulty}`)
            let arrayDataResponse = await response.data

            // This sets the data to question array so that it is accessible outside of this function
            setQuestionArray(arrayDataResponse)

            // this outputs an empty array
            console.log(questionArray)

        } catch(err){
            console.log(err)
        }

    }

    // This fetches the data on mount
    useEffect(() => { getQuiz() }, [])

    // This will set the data for the elements once the state of the question array has been set from the get request
    useEffect(() => { 

        // This sets the content for the question element
        setQuestion(questionArray[0].question)
        // <h4>{question}</h4>

        // Uncaught TypeError: Cannot read properties of undefined (reading 'question')
    }, [questionArray])
  const getQuiz = async () => {
        try{
            // These values were passed by the difficulty Component
            const categoryName = location.state?.name
            const difficulty = location.state?.difficulty

            // This makes a get request to get data for the quiz
            let response = await axios.get(`https://the-trivia-api.com/api/questions?categories=${categoryName}&limit=10&difficulty=${difficulty}`)
            let arrayDataResponse = await response.data

            // This sets the data to question array so that it is accessible outside of this function
            setQuestionArray(arrayDataResponse)
//Solution 
// set question from here 
 setQuestion(arrayDataResponse[0].question)

            // this outputs an empty array
            console.log(questionArray)

        } catch(err){
            console.log(err)
        }

    }
// then you don't need to run useEffect for this , Your state will be fiilled with api response
// not required code below
    useEffect(() => { 

        // This sets the content for the question element
        setQuestion(questionArray[0].question)
        // <h4>{question}</h4>

        // Uncaught TypeError: Cannot read properties of undefined (reading 'question')
    }, [questionArray])


I'm guessing that your state is defined something like this...

const [questionArray, setQuestionArray] = useState([]);
const [question, setQuestion] = useState(/* some initial value */);

This means that when your component is initialised and mounted, questionArray is an empty array.

Effect hooks not only execute when their dependencies change but also when they are initialised. That means when this hook first runs...

useEffect(() => {
  setQuestion(questionArray[0].question);
}, [questionArray]);

It's trying to access .question on undefined , hence your error.


I would skip the question state and the above hook entirely. If you want something to represent the optional first question, you can use a memo hook instead

const firstQuestion = useMemo(() => questionArray[0]?.question, [questionArray]);

or simply use questionArray[0]?.question directly without any hooks.

This will either return the first question property or undefined which you can detect using conditional rendering

{firstQuestion && (
  <p>{firstQuestion}</p>
)}
{/* or */}
{questionArray.length > 0 && (
  <p>{questionArray[0].question}</p>
)}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM