-1

I'm trying to display all the questions from this data set however it's only working sometimes and then other times I receive 'questions is undefined'.

Why am I receiving this error?

const [questions, setQuestions] = useState<any>();
const [question, setQuestion] = useState<string>()
const [answers, setAnswers] = useState<[]>()

useEffect(() => {
    fetch("/environment_questions")
      .then((response) => response.json())
      .then((data) => setQuestions(data));
    }, []);
  
    useEffect(() => {
      if (questions.length > 0) {
        for (let i = 0, l = questions.length; i < l; i++) {
          setQuestion(questions[i].question)
          setAnswers(questions[i].answers)
        }
      }
    }, [questions])
return (
<p>{JSON.stringify(question)}</p>
      <p>{JSON.stringify(answers)}</p>
)
}

Data I'm trying to access: [{"id":1,"question":"...":[{"id":1,"answer":"..."},{"id":2,"answer":"..."}]},{"id":2,"question":"...","answers":[{"id":1,"answer":""},{"id":2,"answer":""},{"id":3,"answer":""}]} ...}]

SK1dev
  • 1,049
  • 1
  • 20
  • 52
  • Thanks but unfortunately this isn't working for me. @David – SK1dev Jun 02 '23 at 14:44
  • Using the information from that question and its solution, what is your updated code and what specifically is failing? In the code shown I would fully expect this to fail for a couple of reasons. One is the proposed duplicate, you're trying to access a state value immediately after setting it, but state updates are asynchronous. Another is you're trying to access that state value immediately after invoking an AJAX operation, which is also asynchronous, so you're trying to access the state value before it's even been set in the first place. Please update the question to the new problem. – David Jun 02 '23 at 14:48
  • For the problem of trying to use a value from an AJAX operation, that duplicate would be: [How do I return the response from an asynchronous call?](https://stackoverflow.com/q/14220321/328193) – David Jun 02 '23 at 14:51
  • I tried adding the dependency in the useEffect but I still received the same error. Thanks for explaining the issues, I understand now but after looking through the questions and solutions, I'm still not sure how to adapt my code. @David – SK1dev Jun 02 '23 at 15:05
  • The answer below demonstrates how you'd apply the solution in the first duplicate, and that solution simultaneously corrects the problem of the second duplicate. You are encouraged to attempt that solution and re-test. If, after attempting to correct the problem, something is still failing, please update the question to include the current code and what specifically is failing. Again... *The code shown* fails for the reasons indicated in the duplicates. If you've *made changes* and something is still failing, we can't help without knowing what those changes are and what is failing. – David Jun 02 '23 at 15:10
  • Ok thanks, I've updated the code in my question using the answer below but I'm still receiving 'questions is undefined'. @David – SK1dev Jun 02 '23 at 15:23
  • 1
    Ah, I bet the second effect is also running on the initial component mount. And `questions` is indeed `undefined` by design. Since the condition in that effect checks the length of `questions` (thereby assuming that it's an array), define it as an array to begin with: `useState([])` – David Jun 02 '23 at 15:25
  • Thanks a lot, setting the default value as an array worked!! @David – SK1dev Jun 02 '23 at 15:30

2 Answers2

1
import React, { useEffect, useState } from 'react'

const Component = () => {
  const [questions, setQuestions] = useState<any>()
  const [question, setQuestion] = useState<string>()
  const [answers, setAnswers] = useState<[]>()

  useEffect(() => {
    fetch('/...')
      .then(response => response.json())
      .then(data => setQuestions(data))
  }, [])

  useEffect(() => {
    if (questions.length > 0) {
      for (let i = 0, l = questions.length; i < l; i++) {
        setQuestion(questions[i].question)
        setAnswers(questions[i].answers)
      }
    }
  }, [questions])

  return (
    <>
      <p>{JSON.stringify(question)}</p>
      <p>{JSON.stringify(answers)}</p>
    </>
  )
}

export default Component
Neo
  • 467
  • 1
  • 3
  • 17
1

try to set values for states like empty string and empty array.

const [questions, setQuestions] = useState<any>("")
const [question, setQuestion] = useState<string>("")
const [answers, setAnswers] = useState<[]>([])

When app loads it try to access state value of state, which is not set yet by useEffect and in Your case is undefined.