我是React的新手,我想知道当我在其中复制对象时何时影响状态对象。
在以下代码中;第一种情况导致状态对象被更新,而第二种情况不是。 我需要知道有什么区别以及为什么会发生这种情况?
import React, { Component } from "react";
export class Test extends Component {
state = {
counters: [
{ id: 1, desc: "Item1 default description" },
{ id: 2, desc: "Item2 default description" }
]
};
handleAction() {
const counters = { ...this.state.counters };
////First Scenario
console.log("Item description before updating:", counters[0].desc);
counters[0].desc = "Item1 description updated successfully!"; //<--This line makes the state updated
console.log("Item description after updating:", counters[0].desc);
console.log(
"Item description value in state object:",
this.state.counters[0].desc //Item value is updated in the state object.
);
////Second Scenario
// console.log("Item description before updating:", counters[0].desc);
// counters[0] = { id: 1, desc: "Item1 description updated successfully!" }; //<--This line does NOT affect the state
// console.log("Item description after updating:", counters[0].desc);
// console.log(
// "Item description value in the state object:", //Item value is NOT updated in the state object.
// this.state.counters[0].desc
// );
}
render() {
return (
<React.Fragment>
{this.state.counters[0].desc}
<button
className="btn btn-danger btn-sm"
onClick={() => this.handleAction()}
>
Check Item description in state object
</button>
</React.Fragment>
);
}
}
答案 0 :(得分:2)
在JS中,对象是passed by reference。并且以下语法复制该数组,但不复制存储在其中的对象。它称为浅表副本。
const counters = { ...this.state.counters };
在第一种情况下,您正在更新对对象的引用,该对象也被state
变量引用。
但是,当您分配数组的元素时,您正在创建state
不知道的新对象,因此它不会被修改。
答案 1 :(得分:0)
您需要使用setState
更新状态。直接更改状态是您不应该做的事情:https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly
答案 2 :(得分:0)
传播运算符{ ...obj }
进行浅表复制,这意味着在这种情况下它仅复制计数器数组的结构,而不复制每个元素的内容。
意味着counter[0]
和counter[1]
的地址或引用是重复的,而不是它们所保存的对象。因此,更新counter[0].desc
也将更新原始状态对象中的desc
属性。
但是更新counter[0]
仅更新重复项,不会影响状态对象中的原始副本。
选中this post,以更好地理解浅层副本和深层副本。
我还必须补充一点,您应该始终使用this.setState更新反应状态,以避免意外结果。
最后,有些人会争论使用嵌套属性,因为React不适合使用嵌套状态。也许这是正确与否,但这是我的想法:
我建议您避免使用嵌套状态,如果您必须尽力使其尽可能轻便,因为不利之处在于每一个微小的更改都会重新创建父对象,这不利于性能。