更改子组件状态会更改父组件道具

时间:2017-07-26 05:14:32

标签: javascript reactjs redux immutability

父组件是标题

子组件是表单,用于更改在触发redux操作的保存后出现在标题中的值。

我用

设置子状态
constructor(props) {
    super(props);
    this.state = {
      object: { ...props.object },
      hidden: props.hidden,
    };
}

表单用于呈现state.object并修改state.object。 当我修改state.object时,父组件的props也会改变。

handleObjectChange = (event, key, subkey) => {
    console.log('props', this.props.object.params);
    console.log('state', this.state.object.params);
    event.preventDefault();
    const value = this.handlePeriod(event.target.value);
    this.setState((prevState) => {
      const object = { ...prevState.object };
      object[key][subkey] = value;
      return { object };
    });
}

控制台输出:

newvalueijusttyped
newvalueijusttyped

这种行为实际上一直到修改redux存储而没有调度动作。

非常感谢这个问题的解决方案

更新

将构造函数更改为此解决了问题

constructor(props) {
    super(props);
    this.state = {
      object: JSON.parse(JSON.stringify(props.object)),
      hidden: props.hidden,
    };
 }

为什么对象传播运营商没有实现我想要实现的目标?

2 个答案:

答案 0 :(得分:1)

Javascript对象是通过引用分配的,所以当你这样做时

constructor(props) {
    super(props);
    this.state = {
      object: props.object,
      hidden: props.hidden,
    };
}

state引用redux state object(如果它是re​​dux状态)。所以现在当你使用

this.setState((prevState) => {
  const object = { ...prevState.object };
  object[key][subkey] = value;
  return { object };
});

虽然您会假设已将对象值克隆到新对象中。但是,Spread语法只对对象的一个​​级别副本。

来自 Spread Syntax MDN docs

  

注意:传播语法在复制时有效地深入一级   阵列。因此,它可能不适合复制多维   数组如下例所示(它与...相同)   Object.assign()和spread语法)。

     

var a = [1,[2],[3]]; var b = [... a]; 。b.shift()移位(); // 1 //   现在阵列a也受到影响:[[],[2],[3]]

如此有效

object[key][subkey] = value;

直接在redux store中更改值。

解决方案是创建一个嵌套副本,如

  const object = { ...prevState.object,
                      [key]: {
                          ...prevState[key],
                          [subkey]: { ...prevState[key][subkey]}
                      }
                   };
  object[key][subkey] = value;

答案 1 :(得分:0)

javascript中的对象通过引用'传递。

如果您将父级的道具作为状态传递给子级,那么当您更改状态时,您实际上是在改变传递给它的同一个对象。

使用Object.assign()创建数据的克隆,然后再将其作为子状态的一部分。