我正在尝试向调查对象添加一个部分及其抛出状态突变错误。
这是我调用动作创建者的方法,该动作创建者将整个调查对象作为参数。
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是否会在调查中复制每个嵌套对象,如果我只是在调查对象的最顶层使用它,就像我在这里使用它一样?
答案 0 :(得分: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的reducer,以返回将在您的this.props.survey上更新的新状态副本。 / p>
另外,建议在object.assign上使用对象扩展语法以获得更好的语法,请参阅此处:http://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html
和
这里有关于使用mapStateToProps的提示: https://github.com/reactjs/react-redux/blob/master/docs/api.md
答案 1 :(得分: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个选择:
答案 2 :(得分:0)
您可以使用spread运算符以ES6方式克隆对象:
let newSurvey = {...this.state.survey}