React - redux状态突变错误

问题描述 投票:0回答:3

我试图向调查对象添加一个部分及其抛出状态突变错误。

这是我调用动作创建者的方法,该动作创建者将整个调查对象作为参数。

   addNewSection(sectionName){
   const id = performance.now();
    let newSurvey = Object.assign({}, this.state.survey);
    const section = Object.assign({},{
        "type": "section",
        "id": id,
        "title": sectionName,
        "position": {
            "offset": 0,
            "width": 12,
            "order": 1
        },
        "items": []
    });
    newSurvey.layout.sections.push(section);
    this.setState({survey: newSurvey});
    this.props.actions.updateSurvey(newSurvey);
}

动作创作者:

export function updateSurvey(survey){
return {type:types.ADD_SECTION_SUCCESS, survey};
}

减速器:

export default function surveyReducer(state = initialState.survey, action){
switch(action.type){

    case types.ADD_SECTION_SUCCESS:
        return action.survey;

    default:
         return state
    }    
}

状态对象的形式如下:

survey: {
layout: {
    sections: [{},{},{}]
    },
    questions:[{},{},{}]
}

我一定是误解了Object.assign。 Object.assign是否会在调查中制作每个嵌套对象的副本,如果我只是在调查对象的最顶层使用它,就像我在这里使用它一样?

javascript reactjs redux frontend mutation
3个回答
1
投票

首先,上述解决方案完全错误。 Object.assign和ES6扩展运算符永远不会在诸如你的深层嵌套数据结构上工作。它们不会阻止任何状态突变。

其次,状态变异错误总是与REDUX的状态有关,而不是与本地状态有关。

export default function headerReducer(state = {userName: ''}, action) {
    switch (action.type) {
        case 'SSO_USER_ACTION':
        {
            return Object.assign({}, state, { userName: action.payload });
        }
        default:
            return state;
    }
}

检查上面的样品减速器。这里我们总是使用以下命令返回一个新对象:

return Object.assign({}, state, { userName: action.payload });

但是,在您的情况下,状态对象“调查”并不那么简单。它是深度嵌套的,Object.assign或者扩展运算符根本不能帮助防止突变。你有3个选择:

  1. 使用不可变JS库,它提供永远不会变异的映射和列表。
  2. 使用规范化库来平整您的状态。
  3. (一种不需要额外库的脏方法)使用以下解决方案修复突变。

enter image description here


1
投票

看起来你对状态应该变异的地方感到有些困惑。看起来你在addNewSection函数中根本没有使用redux状态。您只是更新本地组件状态。你甚至不需要使用object.assign在这里你可以更新本地状态并随意改变它你喜欢。

当您将新调查作为调查状态返回时,您会在减速器中改变您的状态。

您需要使用connect和mapStateToProps()从props访问您的调查状态。然后,您可以在reducer中使用object.assign逻辑来返回状态的新副本。

function mapStateToProps(state) {
  return { survey: state.survey }
}

您可以从this.props.survey访问调查并将其显示在您想要的位置。

在addNewSection()函数中根本不需要object.assign。只需创建新的部分变量,将其传递给您的动作创建者,您的动作创建者就会将其发送到您将使用object.assign的减速器,以返回将在您的this.props.survey上更新的新状态副本。

另外,建议在object.assign上使用对象扩展语法以获得更好的语法,请参见:qazxsw poi

这里有关于使用mapStateToProps的提示:http://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html


0
投票

您可以使用spread运算符以ES6方式克隆对象:

https://github.com/reactjs/react-redux/blob/master/docs/api.md
© www.soinside.com 2019 - 2024. All rights reserved.