Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React-redux状态变异错误_Javascript_Reactjs_Redux_Frontend_Mutation - Fatal编程技术网

Javascript React-redux状态变异错误

Javascript React-redux状态变异错误,javascript,reactjs,redux,frontend,mutation,Javascript,Reactjs,Redux,Frontend,Mutation,我正在尝试向测量对象添加一个截面及其抛出状态 这就是我调用action creator的方法,它将整个测量对象作为参数 addNewSection(sectionName){ const id = performance.now(); let newSurvey = Object.assign({}, this.state.survey); const section = Object.assign({},{ "type": "section",

我正在尝试向测量对象添加一个截面及其抛出状态

这就是我调用action creator的方法,它将整个测量对象作为参数

   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是否会复制测量中的每个嵌套对象,如果我只是在测量对象的最顶层使用它,就像我在这里使用它一样?

您可以使用spread操作符以ES6方式克隆对象:

let newSurvey = {...this.state.survey}

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

let newSurvey = {...this.state.survey}

看起来您对状态应该在哪里发生变异有点困惑。看起来您根本没有在addNewSection函数中使用redux状态。您只是在更新本地组件状态。您甚至不需要使用object.assign。您可以在此处更新本地状态并根据需要对其进行修改

当您将新调查返回为调查状态时,可以在reducer中更改您的状态

您需要使用connect和mapStateToProps()从props访问测量状态。然后,您可以使用减速器中的object.assign逻辑返回状态的新副本

function mapStateToProps(state) {
  return { survey: state.survey }
}
您可以从此.props.survey访问调查,并将其显示在所需的位置

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

此外,建议在object.assign上使用object spread语法。有关更好的语法,请参见此处:

以下是有关使用MapStateTops的提示:

看起来您对状态应该在哪里发生变异有点困惑。看起来您根本没有在addNewSection函数中使用redux状态。您只是在更新本地组件状态。您甚至不需要使用object.assign。您可以在此处更新本地状态并根据需要对其进行修改

当您将新调查返回为调查状态时,可以在reducer中更改您的状态

您需要使用connect和mapStateToProps()从props访问测量状态。然后,您可以使用减速器中的object.assign逻辑返回状态的新副本

function mapStateToProps(state) {
  return { survey: state.survey }
}
您可以从此.props.survey访问调查,并将其显示在所需的位置

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

此外,建议在object.assign上使用object spread语法。有关更好的语法,请参见此处:

以下是有关使用MapStateTops的提示:
首先,上面提到的解决方案是完全错误的。Object.assign和ES6 spread运算符从来不会在像您这样的深度嵌套数据结构上工作。它们不会阻止任何状态突变

其次,状态突变错误总是与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 });
但是,在您的例子中,状态对象“survey”并没有那么简单。它嵌套很深,Object.assign或spread操作符根本无助于防止变异。您有3种选择:

  • 使用不可变的JS库,它提供了永远不会改变的映射和列表
  • 使用规范化库来展平您的状态
  • (一种不需要额外库的肮脏方法)使用下面的解决方案修复突变

  • 首先,上面提到的解决方案是完全错误的。Object.assign和ES6 spread运算符从来不会在像您这样的深度嵌套数据结构上工作。它们不会阻止任何状态突变

    其次,状态突变错误总是与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 });
    
    但是,在您的例子中,状态对象“survey”并没有那么简单。它嵌套很深,Object.assign或spread操作符根本无助于防止变异。您有3种选择:

  • 使用不可变的JS库,它提供了永远不会改变的映射和列表
  • 使用规范化库来展平您的状态
  • (一种不需要额外库的肮脏方法)使用下面的解决方案修复突变

  • 我百分之百同意你的看法,我以前也是这样做的。但是我的领导建议这样做。。顺便说一句,他也是个新手。所以我用了这个方法。假设我按照你说的做,在reducer中,我是否必须这样做:返回Object.assign({},survey,{layout:Object.assign({},survey.layout,{items:[…survey.layout.items,section]});例如:return Object.assign({},survey}换句话说,我必须复制调查中的每个对象还是调查中的每个对象。我总是这样做,而且很容易理解。它看起来像:{…state,survey:action.survey}这等于:Object.assign({},state,{survey:action.survey})基本上,您正在替换旧状态,但没有保留相同的对象。object.assign()返回一个新对象。编辑:抱歉,没有正确阅读问题。不,您不需要使用嵌套的object.assigns。只需使用一个object.assign()将状态复制到一个新对象中。object.assign()将状态复制到空对象中,然后将第三个参数复制到上面。因此它不会改变任何内容,只是用空对象进行复制!这不是我在组件中所做的吗