无法弄清楚如何在不会​​导致变异的情况下更改减速器中的状态

时间:2017-09-07 03:21:40

标签: reactjs ecmascript-6 redux react-redux immutability

尝试更新reducer中的状态后,我一直收到以下错误:

  

"错误:在路径中的调度内检测到状态突变:   quiz.questions.0.answer。看一下处理器的减速器   交流..."

我很确定我没有改变原始状态,因为我正在使用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":[]}}"

2 个答案:

答案 0 :(得分:2)

Spread运算符... aka 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};

答案 1 :(得分:1)

此代码正在改变您的状态:

let currentQuestion = newStateObject.questions.find(x => x.id ==
    parseInt(action.data.questionId));
currentQuestion.answer = action.data.answer;

Object.assign没有进行深层克隆,而您的newStateObject肯定与原始state不一致,currentQuestion正在从{questions数组中提取1}} 与原始状态对象图中的相同。

您可能希望查看类似Immutable.js的内容,但请按照以下方式考虑:您想要更改的实际对象需要替换,其父级(引用它的对象/数组)等等也是如此直到你的州的顶部。如果您使用的是combineReducers,则只需要担心该切片的顶部,因为combineReducers完成了上面的工作。