我目前正在学习 React 并试图了解如何在函数组件中正确更新状态。
我从 React 文档中的“状态和生命周期”部分了解到,如果它使用以前的状态,则应该更新状态,如下所示:
// Correct
this.setState((state, props) => ({
counter: state.counter + 1
}));
而不是
// Wrong
this.setState({
counter: this.state.counter + 1,
});
由于 this.props 和 this.state 可能会异步更新,因此您不应依赖它们的值来计算下一个状态。 ( Reference )
现在我想通过使用 State Hook useState
的函数组件来实现相同的目的。
作为示例,如何更新功能组件中的状态 React docs有以下代码片段:
<button onClick={() => setCount(count + 1)}>
Click me
</button>
这相当于类组件中的以下代码:
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
但这不是“错误”的解决方案吗,因为它直接依赖于国家?
最佳答案
But isn't this the "wrong" solution because it relies directly on the state?
setState
将新状态合并到旧状态中。并以“零碎”的方式进行,例如新状态可以包含旧状态数据的一小部分。因此,在 setState
主体中保留旧状态并使用
this.setState(oldState => ({ ...oldState, someProp: true }) )
“显式”更好,因为它表明您对 setState
无论如何都会执行的操作不抱任何幻想:即使您没有这样做,也会进行合并。
useState
用新状态替换旧状态,因此访问 oldState 的需求不那么迫切。虽然我不介意。
对于异步更新
,setState
和useState
都可以批量更新。尽管 useState
在处理待处理的 Promise 时不会进行批处理,这与示例中的 count + 1
等现成可用值相反。
回到setState
,还有一个原因可以解释为什么setState(oldState => ({...})
的风格更好。记住,setState
无论如何都会进行合并。如果使用 setState(newValue)
风格,则与批处理相结合,可能会导致 React 执行以下代码:
Object.assign(oldState, newValue1, newValue2, newValue3)
其中值 newValueX
是批量更新。 Object.assign
确保“最后更新获胜”。如果一系列 newValueX
表示连续尝试递增同一计数器,那么它可能无法按预期工作。因此 setState
的其他风格更好。使用 useState
和批处理,这种危险似乎仍然存在。
关于javascript - 使用 State Hook 正确设置状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58025996/