用 setInterval 改变 useState 的值

Posted

技术标签:

【中文标题】用 setInterval 改变 useState 的值【英文标题】:change the value of useState with setInterval 【发布时间】:2021-04-24 05:50:59 【问题描述】:

我有一个带有 useState 的简单组件,每次点击都会增加一个计数器 -

function Counter() 
  let [counter, setCounter] = useState(0);

  const incCounter = () => 
    setCounter(counter + 1);
  ;

  return (
    <div className="App">
      <h1>counter</h1>

      <button onClick=incCounter>Inc</button>
    </div>
  );

Here is its demo

现在我想每1秒调用一次增加函数,所以我将这段代码添加到组件函数中-

useEffect(() => 
    setInterval(() => 
      incCounter();
    , 1000);
  , []); 

Here is its demo

但我没有看到组件中的计数器增加了。

我应该如何正确编写它并看到计数器按预期每 1 秒增加一次?

【问题讨论】:

【参考方案1】:

问题

你有一个陈旧的状态值,它来自设置计时器回调的渲染周期。

解决方案

使用功能状态更新,以便从前一个状态更新状态,而不是更新排队的渲染周期中的状态。这允许间隔回调 单击处理程序以无缝更新状态,彼此独立。

setCounter(counter => counter + 1);

事实上,您应该随时使用功能状态更新,下一个状态值取决于任何先前的状态值。递增计数器是使用功能更新的经典示例。

不要忘记返回一个清理函数来清除组件取消的时间间隔。

完整代码

function Counter() 
  let [counter, setCounter] = useState(0);

  const incCounter = () => 
    setCounter((counter) => counter + 1);
  ;

  useEffect(() => 
    const timerId = setInterval(() => 
      incCounter();
    , 1000);

    return () => clearInterval(timerId);
  , []);

  return (
    <div className="App">
      <h1>counter</h1>

      <button onClick=incCounter>Inc</button>
    </div>
  );

演示

【讨论】:

很好的答案,我只想在 useEffect 钩子中添加间隔的清理 @nbokmans 与问题无关,但关于正确的生命周期维护的重要而有效的观点,更新的答案。谢谢。

以上是关于用 setInterval 改变 useState 的值的主要内容,如果未能解决你的问题,请参考以下文章

反应 setInterval 行为

UseEffect 中的 SetInterval 无延迟

反应 useEffect 和 setInterval

如何在反应中使用 setInterval?

useReducer 和 useState

setstate 回调后 useState 不改变?