我目前正在学习React,并试图了解如何正确地更新功能组件中的状态。
我从React文档的“状态和生命周期”部分了解到,如果它使用的是以前的状态,则应更新状态,如下所示:
// Correct
this.setState((state, props) => ({
counter: state.counter + 1
}));
代替
// Wrong
this.setState({
counter: this.state.counter + 1,
});
由于this.props和this.state可能是异步更新的,因此不应依赖于它们的值来计算下一个状态。(Reference)
现在,我想使用状态挂钩useState
使用功能组件来实现相同的目的。
例如,如何更新功能组件中的状态,React docs具有以下代码段:
<button onClick={() => setCount(count + 1)}>
Click me
</button>
等效于类组件中的以下代码:
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
但这不是“错误的”解决方案,因为它直接依赖于状态吗?
答案 0 :(得分:1)
您可以执行以下操作。
import React, { userState } from 'react';
function TestHook() {
const [count, setCount] = useState(0);
function updateCount() {
setCount(count + 1);
}
return <button onClick={handleCount}>{count}</button>
}
在这里检查。 https://codesandbox.io/s/one-with-the-hook-0yig1
您可以在我的中级帖子(https://blog.usejournal.com/getting-started-with-react-hooks-f0b5c1e3e0e7)中关注它
答案 1 :(得分:1)
但这不是“错误的”解决方案,因为它直接依赖于状态吗?
setState
合并新状态到旧状态。并以“零碎”的方式进行,例如新状态可以包含旧状态数据的一小部分。因此,将旧状态放在setState
主体内部并使用
this.setState(oldState => ({ ...oldState, someProp: true }) )
明确合并它是有益的
“显式”更好,因为它表明您对setState
仍然会做的事情不抱任何幻想:即使没有,也要合并。
useState
用新状态替换旧状态,因此访问oldState的需求并不那么迫切。即使我不介意。
对于updated asynchronously
,setState
和useState
都可以批量更新。尽管useState
在处理待处理的Promises时不会进行批处理,但与样本中的count + 1
这样的现成可用值相反。
回到setState
,还有味道setState(oldState => ({...})
更好的另一个原因。请记住,setState
始终会合并。如果使用了风味setState(newValue)
,则与批处理结合使用,可以导致以下代码由React执行:
Object.assign(oldState, newValue1, newValue2, newValue3)
其中值newValueX
是批处理更新。 Object.assign
确保“最后更新获胜”。如果newValueX
系列表示连续尝试增加同一计数器,则它可能无法按预期工作。因此,setState
的其他味道更好。使用useState
进行批处理后,这种危险似乎仍然存在。