Reputation: 1492
I keep getting the following error thrown after trying to update state in my reducer:
"Error: A state mutation was detected inside a dispatch, in the path:
quiz.questions.0.answer
. Take a look at the reducer(s) handling the ac..."
I'm pretty sure I am not mutating the original state as I am using object.assign yet the error persists.
My reducer:
case types.UPDATE_QUIZ_ANSWER:
let newStateObject = Object.assign({}, state);
let currentQuestion = newStateObject.questions.find(x => x.id == parseInt(action.data.questionId));
currentQuestion.answer = action.data.answer;
return Object.assign({}, newStateObject);
My state object:
{"questions":
[{"id":1,"questionText":"Camps is?","multipleChoiceOption1":
{"value":"1","label":"Great"},"multipleChoiceOption2":
{"value":"2","label":"Fun"},"multipleChoiceOption3":
{"value":"3","label":"Awesome"},"multipleChoiceOption4":
{"value":"4","label":"All of the above"},
"answer":"2"},
{"id":2,"questionText":"At Camps we will?","multipleChoiceOption1":
{"value":"1","label":"AAA"},"multipleChoiceOption2":
{"value":"2","label":"Adult Focused"},"multipleChoiceOption3":
{"value":"3","label":"CCC"},"multipleChoiceOption4":
{"value":"4","label":"All of the above"},
"answer":"3"}],
"results":
{"quizPass":false,"quizResults":[]}}"
Upvotes: 0
Views: 897
Reputation: 9119
Spread operator ...
aka Object.assign
works only on the first level of object properties.
let newStateObject = Object.assign({}, state);
let currentQuestion = newStateObject.questions.find(x => x.id == parseInt(action.data.questionId));
currentQuestion.answer = <----- here is the mutation
What you can do is to create a copy of object at each level:
// make a copy of the array
let newQuestions = [...newStateObject.questions];
let questionIndex = newQuestions.findIndex(x => x.id == parseInt(action.data.questionId));
// update array and question
newQuestions[questionIndex] = {...newQuestions[questionIndex], answer: action.data.answer};
// return new result
return {...state, questions: newQuestions};
Upvotes: 2
Reputation: 84724
This code is mutating your state:
let currentQuestion = newStateObject.questions.find(x => x.id ==
parseInt(action.data.questionId));
currentQuestion.answer = action.data.answer;
Object.assign
does not deep clone so, while your newStateObject
is certainly not the same as your original state
, the currentQuestion
you are pulling from the array of questions
is the same as in the original state object graph.
You may want to look into something like Immutable.js, but think about it like this: the actual object you want to change needs to be replaced, as does its parent (the object/array that references it) and so forth until the top of your state. If you are using combineReducers
you only have to worry about the top of that slice since combineReducers
does the work above that.
Upvotes: 1