【问题标题】:Infinity loop using useState with useEffect in React在 React 中使用 useState 和 useEffect 的无限循环
【发布时间】:2020-12-04 01:33:00
【问题描述】:

我想在每一秒之后增加状态 [second] = [second + 1]。

const [second,setSecond] = useState(0);
useEffect(() => {
    const interval = setInterval(() => {
      setSecond(second+1)
    }, 1000);
    return () => clearInterval(interval);
}, []);

但似乎出现了一个无限循环,[秒]只增加了一次,从0到1,就停止了运行。

我更改了我的代码

setSecond(second+1)

到

setSecond((second) => {return second+1})

这个运行没有问题:

const [second,setSecond] = useState(0);
useEffect(() => {
    const interval = setInterval(() => {
      setSecond((second) => {return second+1})
    }, 1000);
    return () => clearInterval(interval);
}, []);

说真的,我还是没搞清楚。谁能向我解释为什么?提前致谢!

【问题讨论】:

    标签: reactjs use-effect use-state


    【解决方案1】:

    查看您的代码,我认为问题在于 second 的值绑定为 0。

    const [second,setSecond] = useState(0);
    useEffect(() => {
        const interval = setInterval(() => {
          setSecond(second+1)
        }, 1000);
        return () => clearInterval(interval);
    }, []);
    

    在这里,当您的组件挂载时,将执行 useEffect。那时您正在创建一个函数并将其传递给 setInterval。该函数将使用创建时second 的值(等于0)。所以每次 setInterval 运行时,它都会执行setSecond(0+1),它总是等于 1。

    你提到的正确方法是有效的,因为你给它一个函数,每次执行时都会将状态的当前值传递给它。

    【讨论】:

      【解决方案2】:

      Ciao,你设置second的两种方式不一样。

      这边:

      setSecond(second+1)
      

      不考虑second 的previuos 值。它只是通过读取second 的当前值来尝试将秒增加 1。考虑到setSecond 是异步的,下一个setInterval 不能保证second 会被上一个setSecond 更新。所以这样你可能会出现故障。

      这边:

      setSecond((second) => {return second+1})
      

      是正确的。在这里,您正在考虑 second 的 previuos 值(通过使用箭头函数)。所以在这种情况下,second 将被正确更新。

      你可以做一个测试:拿一个按钮,onclick函数尝试写:

      setSecond(second+1)
      setSecond(second+1)
      

      您会看到second 将增加 1(而不是预期的 2)。

      现在像这样修改你的代码:

      setSecond((second) => {return second+1})
      setSecond((second) => {return second+1})
      

      您会看到second 将增加 2!

      这是因为 Hooks 是异步的。

      【讨论】:

      • 没问题。很高兴为您提供帮助:)
      猜你喜欢
      • 2020-02-21
      • 2021-05-17
      • 1970-01-01
      • 2021-08-28
      • 2021-01-31
      • 2020-04-14
      • 1970-01-01
      • 2020-09-06
      相关资源
      最近更新 更多