gpt4 book ai didi

javascript - 如何在 React 中更新嵌套状态,状态应该是不可变的吗?

转载 作者:数据小太阳 更新时间:2023-10-29 05:31:54 26 4
gpt4 key购买 nike

我们正在热烈讨论如何在 React 中更新嵌套状态。状态是否应该是不可变的?优雅地更新状态的最佳做法是什么?

假设您的状态结构如下所示:

this.state = { 
numberOfStudents: "3",
gradeLevel: "5",
students : [
{ id : "1234",
firstName: "John",
lastName: "Doe",
email: "johndoe@mail.com"
phoneNumer: "12345"

},
{ id : "56789",
firstName: "Jane",
lastName: "Doe",
email: "janedoe@mail.com"
phoneNumer: "56789"
},
{ id : "11111",
firstName: "Joe",
lastName: "Doe",
email: "joedoe@mail.com"
phoneNumer: "11111"
}
]
}

然后我们要更新 joe doe 的电话号码。我们可以通过几种方式做到这一点:

改变状态+强制更新重新渲染

this.state.students[2].phoneNumber = "9999999";
this.forceUpdate();

改变状态+改变状态的setState

this.state.students[2].phoneNumber = "9999999";
this.setState({
students: this.state.students
});

Object.assign,这仍然会改变状态,因为 newStudents 只是对 this.state 指向的同一对象的新引用

const newStudents = Object.assign({}, this.state.students);
newStudents[2].phoneNumber = "9999999"
this.setState({
students: newStudents
});

更新不变性助手 ( https://facebook.github.io/react/docs/update.html ) + setState。如果我们在每个学生对象中都有 address.street、address.city、address.zip 并且想要更新街道,这会很快变得很糟糕。

const newStudents = React.addons.update(this.state.students, {2: {phoneNumber: {$set:"9999999"}}});
this.setState({
students: newStudents
})

setState 的 react 文档的最后一行指出:

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable. https://facebook.github.io/react/docs/react-component.html

文档指出我们不应该使用 forceUpdate 来重新渲染:

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().

为什么会这样,如果我们改变状态然后调用 setState 会发生什么?在什么情况下 setState() 会替换我们所做的 mutation?这是一个非常令人困惑的说法。谁能解释一下我们在上面设置状态时使用的每个场景可能出现的复杂情况。

最佳答案

您声明:

“Object.assign,这仍然会改变状态,因为 newStudents 只是对 this.state 指向的同一对象的新引用”

此语句不正确
Object.assign 改变传入其第一个参数的状态。由于您传入了一个空对象文字 ({}),您正在改变新的对象文字 and 而不是 this.state.


一些背景:

不可变状态的原理与函数式编程有关。

It is useful in React because it provides a way for React to know if the state has changed at all, one use case it is useful is for optimising when components should re-render

考虑具有嵌套对象的复杂状态的情况。改变状态的值会改变状态中的属性值,但不会改变对象的引用。

this.state = {nestObject:{nestedObj:{nestObj:'yes'}}};

// mutate state
this.state.nestObject.nestedObj.nestObj= 'no';

我们如何知道 React 是否应该重新渲染组件?

  1. 深度平等检查?想象一下这在一个复杂的状态下会是什么样子,每个状态更新都要进行数百次甚至数千次检查...
  2. 无需检查更改,只需强制 React 在每次状态更改时重新渲染所有内容...

是否可以替代后两种方法?


不可变方式

通过创建一个新对象(以及一个新引用),使用 Object.assign 复制旧状态并改变它,您可以操纵状态值并更改对象引用。

通过不可变状态方法,我们可以通过简单地检查对象引用是否相等来知道状态是否发生了变化。

下面评论中反对者的简化示例:

考虑这个简单的例子:

this this.state = { someValue: 'test'}
var newState = Object.assign({}, this.state);
console.log(newState); // logs: Object {someValue: "test"]
console.log(this.state); // logs: Object {someValue: "test"]

// logs suggest the object are equal (in property and property value at least...

console.log(this.state === this.state); // logs: true

console.log(this.state === newState); // logs: false. Objects are
// pass-by-reference, the values stored
// stored in this.state AND newState
// are references. The strict equality
// shows that these references
// DON'T MATCH so we can see
// that an intent to modify
// state has been made

关于javascript - 如何在 React 中更新嵌套状态,状态应该是不可变的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42101171/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com