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])
CodePudding user response:
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>
)}
CodePudding user response:
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])