React - redux 状态突变错误
React - redux state mutation error
我正在尝试向调查对象添加一个部分及其抛出状态突变错误。
这是我调用将整个调查对象作为参数的动作创建器的方法。
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 是否会复制调查中的每个嵌套对象,如果我只是在调查对象的最顶层使用它,就像我在这里使用的那样?
您可以使用扩展运算符以 ES6 方式克隆对象:
let newSurvey = {...this.state.survey}
您似乎对应该在何处更改状态感到困惑。看起来您在 addNewSection 函数中根本没有使用 redux 状态。您只是在更新本地组件状态。你甚至不需要在这里使用 object.assign 你可以更新本地状态并随意改变它。
当您 return 将新调查作为调查状态时,您会改变减速器中的状态。
您需要使用 connect 和 mapStateToProps() 从道具访问您的调查状态。然后,您可以在减速器中使用 object.assign 逻辑来 return 状态的新副本。
function mapStateToProps(state) {
return { survey: state.survey }
}
您可以从 this.props.survey 访问调查并将其显示在您想要的位置。
您的 addNewSection() 函数中根本不需要 object.assign。只需创建您的新部分变量,将其传递给您的动作创建者,您的动作创建者会将其分派给您的减速器,您将使用 object.assign 到 return 状态的新副本,该副本将在您的 this.props.survey.
此外,建议在 object.assign 上使用对象扩展语法以获得更好的语法,请参见此处:http://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html
和
此处提供有关使用 mapStateToProps 的提示:
https://github.com/reactjs/react-redux/blob/master/docs/api.md
首先,上面提到的解决方案是完全错误的。 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一个新的对象,使用:
return Object.assign({}, state, { userName: action.payload });
但是,在您的情况下,状态对象 'survey' 并不是那么简单。它嵌套很深, Object.assign OR 展开运算符根本无法防止突变。您有 3 个选项:
- 使用不可变的 JS 库,它提供永远不会被改变的映射和列表。
- 使用规范化库来扁平化你的状态。
- (一种不需要额外库的肮脏方法)使用以下解决方案修复突变。
我正在尝试向调查对象添加一个部分及其抛出状态突变错误。
这是我调用将整个调查对象作为参数的动作创建器的方法。
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 是否会复制调查中的每个嵌套对象,如果我只是在调查对象的最顶层使用它,就像我在这里使用的那样?
您可以使用扩展运算符以 ES6 方式克隆对象:
let newSurvey = {...this.state.survey}
您似乎对应该在何处更改状态感到困惑。看起来您在 addNewSection 函数中根本没有使用 redux 状态。您只是在更新本地组件状态。你甚至不需要在这里使用 object.assign 你可以更新本地状态并随意改变它。
当您 return 将新调查作为调查状态时,您会改变减速器中的状态。
您需要使用 connect 和 mapStateToProps() 从道具访问您的调查状态。然后,您可以在减速器中使用 object.assign 逻辑来 return 状态的新副本。
function mapStateToProps(state) {
return { survey: state.survey }
}
您可以从 this.props.survey 访问调查并将其显示在您想要的位置。
您的 addNewSection() 函数中根本不需要 object.assign。只需创建您的新部分变量,将其传递给您的动作创建者,您的动作创建者会将其分派给您的减速器,您将使用 object.assign 到 return 状态的新副本,该副本将在您的 this.props.survey.
此外,建议在 object.assign 上使用对象扩展语法以获得更好的语法,请参见此处:http://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html
和
此处提供有关使用 mapStateToProps 的提示: https://github.com/reactjs/react-redux/blob/master/docs/api.md
首先,上面提到的解决方案是完全错误的。 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一个新的对象,使用:
return Object.assign({}, state, { userName: action.payload });
但是,在您的情况下,状态对象 'survey' 并不是那么简单。它嵌套很深, Object.assign OR 展开运算符根本无法防止突变。您有 3 个选项:
- 使用不可变的 JS 库,它提供永远不会被改变的映射和列表。
- 使用规范化库来扁平化你的状态。
- (一种不需要额外库的肮脏方法)使用以下解决方案修复突变。