使用状态挂钩正确设置状态

时间:2019-09-20 09:54:04

标签: javascript reactjs

我目前正在学习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>

但这不是“错误的”解决方案,因为它直接依赖于状态吗?

2 个答案:

答案 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 asynchronouslysetStateuseState都可以批量更新。尽管useState在处理待处理的Promises时不会进行批处理,但与样本中的count + 1这样的现成可用值相反。

回到setState,还有味道setState(oldState => ({...})更好的另一个原因。请记住,setState始终会合并。如果使用了风味setState(newValue),则与批处理结合使用,可以导致以下代码由React执行:
Object.assign(oldState, newValue1, newValue2, newValue3)
其中值newValueX是批处理更新。 Object.assign确保“最后更新获胜”。如果newValueX系列表示连续尝试增加同一计数器,则它可能无法按预期工作。因此,setState的其他味道更好。使用useState进行批处理后,这种危险似乎仍然存在。