我们应该使用第一种方法还是第二种方法来更新状态中的设置对象?哪一种是可变的最佳实践?不变的概念?
state = {
settings: {
at: [],
// other keys
}
}
addHour = () => {
const { settings } = this.state;
const time = moment();
time.set({ minutes: 0, seconds: 0 });
// First Way
settings.at.push(time);
this.setState({ settings });
// Second Way
const new_settings = {
...settings
at: [...settings.at, time]
}
this.setState({ settings: new_settings });
};
答案 0 :(得分:2)
代码
const { settings } = this.state;
这并不做任何复制,它只是一个参考,而当您进行settings.at.push(time);
时,实际上是在改变原始对象
let state = {
settings: [1,2,3]
}
let {settings} = state
settings.push(4)
console.log(settings)
console.log(state)
如果您的设置数组始终深一层,则可以使用spread operator
,否则可以使用JOSN.parse(JOSN.stringify())
创建深层克隆
let state = {
settings: [1, 2, 3]
}
let settings = [...state.settings]
settings.push(4)
console.log(settings)
console.log(state)
答案 1 :(得分:1)
以第一种方式,您仍在对原始状态对象进行变异。它称为对原始对象的引用。第二种方法是克隆状态。它有2个不同的对象。
答案 2 :(得分:0)
第一种方法是引用实际状态,对其进行突变。
以第二种方式,您不会改变状态,反正要注意一件事:
该分配类型不是线程安全的,请看以下示例:
const { settings } = this.state;
const time = moment();
time.set({ minutes: 0, seconds: 0 });
// If at this execution point another procedure changes the state (e.g. setting another key in the state object)
const new_settings = {
...settings
at: [...settings.at, time]
};
// You are actually setting an "old" state for some keys
this.setState({ settings: new_settings });
我会去做以下事情:
this.setState(oldSettings => {
const newSettings = {...oldSettings};
//modify the copy newSettings
return newSettings;
});
如果状态很复杂,则必须对其进行深度克隆!