Apologies, I feel like this has been covered thoroughly but none of the Similar Questions quite seem to hit the mark. I've worked with React a lot in the past, but it's been a while and I'm feeling a little rusty...
So in my React (Native, but I don't think that's relevant) app, I have a data object which I pull from an external JSON file, which I store part of in component-level state. This state contains an array of objects questions
.
I have a useEffect where I modify this state object by adding another property shuffled_answers
to each element of the array and set this back to state. This all seems to work totally fine (inspected using console logs and react dev tools and state looks exactly as I would expect).
For some reason though, when I try to use this new property in my JSX it's consistently undefined. Even if I try to conditionally render based on the existence of the property.
Here's an abridged version of my component, any thoughts very welcome. Note that in the 2 console logs in my JSX, in the top one I can see the populated shuffled_answers
property within my object. But in the console log just below it, where I call the property directly, it returns undefined
. Same goes with the conditionally rendered <View>
a few lines below, this never renders even though I can see that shuffled_answers
is part of the object.
const QuizScreen = ({ navigation }) => {
const dispatch = useDispatch()
const selectedLevel = useSelector(state => state.progress.selectedLevel)
const currentQuestionIndex = useSelector(
state => state.progress.currentQuestion,
)
/* Set up some local state (i.e. just for this active quiz view) which doesn't need to be in redux */
const [questionAnswered, setQuestionAnswered] = useState(false)
const [activeQuiz, setActiveQuiz] = useState(
quizData.quizzes.find(quiz => quiz.id === selectedLevel),
)
useEffect(() => {
/* Create an array of shuffled answers within local state */
let mutableActiveQuiz = activeQuiz
mutableActiveQuiz.questions.map((question, i) => {
const allAnswers = [
question.correct_answer,
...question.incorrect_answers,
]
const shuffledAnswers = allAnswers
.map(value => ({ value, sort: Math.random() }))
.sort((a, b) => a.sort - b.sort)
.map(({ value }) => value)
mutableActiveQuiz.questions[i].shuffled_answers = shuffledAnswers
})
setActiveQuiz(mutableActiveQuiz)
}, [])
/* ... */
return (
<View>
{console.log(activeQuiz.questions[currentQuestionIndex])}
{console.log(activeQuiz.questions[currentQuestionIndex].shuffled_answers)}
<Text>Level {selectedLevel}</Text>
<Text>Question {currentQuestionIndex + 1}</Text>
<View>
<Text>
{decode(activeQuiz.questions[currentQuestionIndex].question)}
</Text>
{activeQuiz.questions[currentQuestionIndex].shuffled_answers && (
<View>
{activeQuiz.questions[currentQuestionIndex].shuffled_answers.map(
(answer, i) => {
return (
<Button
key={i}
title={answer}
onPress={() => submitAnswer(answer)}
/>
)
},
)}
</View>
)}
{questionAnswered && (
<View>
<Button
title='Next Question'
onPress={() => {
dispatch(nextQuestion())
setQuestionAnswered(false)
}}
/>
</View>
)}
</View>
</View>
)
}