React中带嵌套数组的父组件Prop为何被状态浅拷贝修改?
问题:修改状态变量的浅拷贝为何会改变传入的Prop?
代码示例
type ObjectWithNestedArray = { array: { name: string }[]; }; const App = () => <Parent />; const Parent = () => { const objWithNestedArray = { array: [{ name: "A" }] }; return <Child objWithNestedArray={objWithNestedArray}></Child>; }; const Child = (props: { objWithNestedArray: ObjectWithNestedArray }) => { const [stateObjWithNestedArray, setStateObjWithNestedArray] = useState<ObjectWithNestedArray>(); const [count, setCount] = useState<number>(0); const onChange = () => { if (stateObjWithNestedArray) { //const copyOfObj = structuredClone(stateObjWithNestedArray) as ObjectWithNestedArray; const copyOfObj = { ...stateObjWithNestedArray }; copyOfObj.array[0].name = "B"; } setCount(count + 1); }; useEffect(() => { if (props.objWithNestedArray) { setStateObjWithNestedArray((current) => props.objWithNestedArray); } }, [props.objWithNestedArray]); return ( <div> <pre>obj={JSON.stringify(props.objWithNestedArray, null, 2)}</pre> <button onClick={() => onChange()}>Click me</button> </div> ); };
现象
- 初始渲染时,Prop显示:
obj={ "array": [ { "name": "A" } ] }
- 点击按钮后,Prop被修改为:
obj={ "array": [ { "name": "B" } ] }
- 若改用
structuredClone生成拷贝,Prop值不会改变。
疑问
在React中Prop应保持不可变的前提下,为何修改状态变量的浅拷贝会改变传入的Prop?是否因为Prop中的数组是按引用传递,浅拷贝仅复制引用,修改数组元素时实则操作原Prop数组的内存地址?
原因解析
你猜的完全正确,核心就是引用传递特性和浅拷贝的局限性:
- 首先,Parent组件中的
objWithNestedArray是包含数组的对象,数组属于引用类型。当它作为Prop传给Child时,传递的是对象的内存引用,而非完整的值副本。 - Child组件的useEffect直接将Prop的引用存入状态,所以
stateObjWithNestedArray和props.objWithNestedArray指向同一块内存中的对象。 - 浅拷贝
{ ...stateObjWithNestedArray }仅复制了外层对象的属性,但内部的array属性依然是原数组的引用——也就是说,copyOfObj.array、stateObjWithNestedArray.array、props.objWithNestedArray.array指向的是同一个数组。 - 因此修改
copyOfObj.array[0].name时,实际操作的是原Prop数组里的元素,最终导致Prop的值被改变。
而structuredClone是深拷贝,它会递归复制所有层级的引用类型,生成完全独立的新对象和数组,修改这个副本自然不会影响原Prop的内容。
内容的提问来源于stack exchange,提问作者Sparm
相关产品推荐
相关产品推荐

