I got a problem with this Function. When I trigger this function it only re render the component the first trigger. After that not any more. I cant find the problem 🙁
function selectAnswer(id, questId) {
let newArr = questions
for(let i = 0; i < newArr.length; i++){
if(questId === newArr[i].id){
const changedAnswers = newArr[i].answers.map(answer => {
return answer.id === id ?
{...answer, selected: !answer.selected} :
{...answer, selected: false}
})
newArr.forEach(element => {
if(questId === element.id){
element.answers = changedAnswers
}
})
}
}
setQuestions(newArr)
}
>Solution :
You’re never actually updating the state. This doesn’t create a copy of the array, it just duplicates a reference to the array:
let newArr = questions
So this isn’t setting state to a new array, but just a reference to the same array:
setQuestions(newArr)
Additionally, instead of creating new state, you are mutating the existing state:
element.answers = changedAnswers
Start by creating a new array, even if it contains the same elements as the original:
let newArr = [...questions];
Then, when you want to modify one of those elements, instead of modifying the existing element you would instead replace it with a new one. So instead of this structure:
newArr.forEach(element => {
});
You could instead replace your new array with a .map() over itself:
newArr = newArr.map(element => {
});
And within that .map() you would return either the unmodified object or the replacement object:
newArr = newArr.map(element => {
if(questId === element.id) {
return {...element, answers: changedAnswers};
} else {
return element;
}
});
Overall, the idea here is that you don’t want to loop over an existing array, modify its values, and set that array back to state. That’s not "updating state" in the React sense but instead it’s "mutating state". Instead, create a new array and populate it with the objects you want. Those objects can be a mix of unchanged objects from the existing array and replaced (not modified) objects from the existing array.