更改 child 组件状态会更改 parent 组件道具
Changing a child components state changes the parent components props
Parent 组件是 header
Child 组件是一个 form,用于在触发 redux 操作的保存后更改出现在 header 中的值。
我用
设置了child状态
constructor(props) {
super(props);
this.state = {
object: { ...props.object },
hidden: props.hidden,
};
}
表单用于渲染state.object和修改state.object。
当我修改 state.object 时,parent 组件的 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,
};
}
为什么 object 展开运算符不能达到我想要达到的目的?
javascript 中的对象是 'passed by reference'。
如果您将父级的道具作为状态传递给子级,那么当您更改状态时,您实际上是在改变传递给它的同一对象。
使用 Object.assign() 创建数据的克隆,然后再将其作为子状态的一部分。
Javascript 对象是通过引用分配的,所以当你这样做时
constructor(props) {
super(props);
this.state = {
object: props.object,
hidden: props.hidden,
};
}
state 引用 redux state object
(如果它是 redux state)。所以现在当你使用
this.setState((prevState) => {
const object = { ...prevState.object };
object[key][subkey] = value;
return { object };
});
虽然您会假设您已将对象值克隆到一个新对象中。然而,Spread 语法只做对象的一级复制。
Note: Spread syntax effectively goes one level deep while copying an
array. Therefore, it may be unsuitable for copying multidimensional
arrays as the following example shows (it's the same with
Object.assign() and spread syntax).
var a = [1, [2], [3]]; var b = [...a]; b.shift().shift(); // 1 //
Now array a is affected as well: [[], [2], [3]]
如此有效
object[key][subkey] = value;
直接在 redux store 中更改值。
解决方案是创建一个嵌套副本,例如
const object = { ...prevState.object,
[key]: {
...prevState[key],
[subkey]: { ...prevState[key][subkey]}
}
};
object[key][subkey] = value;
Parent 组件是 header
Child 组件是一个 form,用于在触发 redux 操作的保存后更改出现在 header 中的值。
我用
设置了child状态constructor(props) {
super(props);
this.state = {
object: { ...props.object },
hidden: props.hidden,
};
}
表单用于渲染state.object和修改state.object。 当我修改 state.object 时,parent 组件的 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,
};
}
为什么 object 展开运算符不能达到我想要达到的目的?
javascript 中的对象是 'passed by reference'。
如果您将父级的道具作为状态传递给子级,那么当您更改状态时,您实际上是在改变传递给它的同一对象。
使用 Object.assign() 创建数据的克隆,然后再将其作为子状态的一部分。
Javascript 对象是通过引用分配的,所以当你这样做时
constructor(props) {
super(props);
this.state = {
object: props.object,
hidden: props.hidden,
};
}
state 引用 redux state object
(如果它是 redux state)。所以现在当你使用
this.setState((prevState) => {
const object = { ...prevState.object };
object[key][subkey] = value;
return { object };
});
虽然您会假设您已将对象值克隆到一个新对象中。然而,Spread 语法只做对象的一级复制。
Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with Object.assign() and spread syntax).
var a = [1, [2], [3]]; var b = [...a]; b.shift().shift(); // 1 // Now array a is affected as well: [[], [2], [3]]
如此有效
object[key][subkey] = value;
直接在 redux store 中更改值。
解决方案是创建一个嵌套副本,例如
const object = { ...prevState.object,
[key]: {
...prevState[key],
[subkey]: { ...prevState[key][subkey]}
}
};
object[key][subkey] = value;