无法弄清楚如何在不引起突变的情况下更改减速器中的状态
Can't figure out how to change State in reducer without causing a mutation
尝试更新我的 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..."
我很确定我没有改变原始状态,因为我正在使用 object.assign 但错误仍然存在。
我的减速器:
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);
我的状态对象:
{"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":[]}}"
此代码正在改变您的状态:
let currentQuestion = newStateObject.questions.find(x => x.id ==
parseInt(action.data.questionId));
currentQuestion.answer = action.data.answer;
Object.assign
没有深度克隆所以,而你的 newStateObject
肯定和你原来的 state
不一样,你从数组中拉取的 currentQuestion
questions
是 与原始状态对象图中相同。
您可能想查看类似 Immutable.js 的内容,但请这样想:您要更改的实际对象需要替换,其父对象(object/array引用它)等等,直到您所在州的顶部。如果您使用的是 combineReducers
,您只需担心 切片 的顶部,因为 combineReducers
会在上面完成工作。
展开运算符 ...
又名 Object.assign
仅适用于对象属性的第一级。
let newStateObject = Object.assign({}, state);
let currentQuestion = newStateObject.questions.find(x => x.id == parseInt(action.data.questionId));
currentQuestion.answer = <----- here is the mutation
您可以做的是在每个级别创建对象的副本:
// 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};
尝试更新我的 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..."
我很确定我没有改变原始状态,因为我正在使用 object.assign 但错误仍然存在。
我的减速器:
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);
我的状态对象:
{"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":[]}}"
此代码正在改变您的状态:
let currentQuestion = newStateObject.questions.find(x => x.id ==
parseInt(action.data.questionId));
currentQuestion.answer = action.data.answer;
Object.assign
没有深度克隆所以,而你的 newStateObject
肯定和你原来的 state
不一样,你从数组中拉取的 currentQuestion
questions
是 与原始状态对象图中相同。
您可能想查看类似 Immutable.js 的内容,但请这样想:您要更改的实际对象需要替换,其父对象(object/array引用它)等等,直到您所在州的顶部。如果您使用的是 combineReducers
,您只需担心 切片 的顶部,因为 combineReducers
会在上面完成工作。
展开运算符 ...
又名 Object.assign
仅适用于对象属性的第一级。
let newStateObject = Object.assign({}, state);
let currentQuestion = newStateObject.questions.find(x => x.id == parseInt(action.data.questionId));
currentQuestion.answer = <----- here is the mutation
您可以做的是在每个级别创建对象的副本:
// 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};