可变的最佳实践|不变的对象

时间:2019-06-14 11:42:31

标签: javascript reactjs ecmascript-6

我们应该使用第一种方法还是第二种方法来更新状态中的设置对象?哪一种是可变的最佳实践?不变的概念?

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 });
};

3 个答案:

答案 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;
});

如果状态很复杂,则必须对其进行深度克隆!