【问题标题】:Can I rely on useState value to calculate the new state?我可以依靠 useState 值来计算新状态吗?
【发布时间】:2020-05-06 17:40:25
【问题描述】:

考虑简单的状态钩子:

const [count, setCount] = React.useState(0);

我想增加或减少计数。基本上做hooks docs中显示的同样的事情。

但作为旧的this.setState 函数的已知fact

因为 this.props 和 this.state 可能是异步更新的,所以你 不应依赖它们的值来计算下一个状态。

根据旧状态更新状态的正确方法是:

this.setState((state) => ({
  counter: state.counter + 1
}));

同样的事情也适用于setCount吗? 或者我可以确定count 始终是最新的?

【问题讨论】:

标签: javascript reactjs react-hooks


【解决方案1】:

useState 挂钩的工作方式与 this.setState 不同。在下面的示例中调用您的设置器 setCount 确实是异步工作的,但由于 count 在功能组件的呈现期间没有更改,因此评估是确定性的。

以下示例是从 React 文档中的 Hooks at a Glance 逐字复制的,它是 100% 安全的(在未安装的组件上调用方法时不会出现任何错误),并且会按预期运行:

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

需要使用功能更新的唯一一次是将函数传递给setCount 是在引用状态时需要多次调用setCount。请注意,这并不是因为 setState 是异步的,而是因为 count 在下一次渲染之前不会更新。

例如,这将是一个问题

<button
  onClick={() => {
    setCount(count + 1)
    setCount(count + 1) // since `count` is not dynamically updated mid-render, this evaluates to the same value as above
  }}
/>

在实践中,这种模式比较少见。您不会以这种方式在单个函数中多次调用 setter。相反,如果您将 setter 作为子项的 prop 传递,并且这些子项引用由 setter 控制的状态,那么您将使用功能更新模式。不过,即使在这种情况下,React will re-render the component with each successive value

【讨论】:

  • 除非 onClick 处理程序是异步的并且在 setCount 之前有一些逻辑
  • @coreyward 问题中是否提供了特定的 onClick 示例?问题是关于 setCount
  • @SaveliTomac 我提供的示例永远不会导致引用未安装的组件,因为 setter (setCount) 在渲染中是稳定的。回调方法和这里使用的直接值方法之间唯一有效的区别是,如果在下一次渲染之前多次触发 onClick 处理程序,则计数只会增加/减少 1。无论如何,这通常是您所期望的——发生线程锁定时排队与 UI 相关的操作会产生大量意外事件。
  • 你为什么说卸载组件?我尝试向您解释,您的示例可以跳过计数器的增量
  • 伙计们,寒冷,毒性无处可去。 @coreyward 感谢您的回答
【解决方案2】:

我不确定确切的逻辑,以及count 状态的用例,但一般情况下,您需要调用

setCount(count + 1); 

或者,使用回调的功能更新

setCount(prev => prev + 1); 

如果您想更新您的状态。但是,请注意状态的更新可以是异步的,这类似于类组件的setState() 的工作方式。您可以参考 useState documentation 了解更多详情。

【讨论】:

    猜你喜欢
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-20
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    相关资源
    最近更新 更多