在useEffect中调用setInterval时会发生什么

时间:2019-06-16 08:12:57

标签: javascript reactjs react-hooks

我有以下反应成分。

function App() {

  const [counter, setCounter] = useState(0);

  useEffect(() => {
    setInterval(() => {
      setCounter(counter+1)
    }, 3000)
  }, [counter]);

  console.log(counter)


  return (
    <div>
      hi
    </div>
  );
}

export default App;

我得到类似

的结果
  

0

     

1

     

1

     

2

     

1

     

2

     

3   ...

我确实知道,每次调用setCounter都会重新渲染组件,并且每次渲染都会重新创建useEffect回调。我的问题是,不应因此而读取当时每个渲染器的计数值

  

1、2、3、4、5 ....

2 个答案:

答案 0 :(得分:2)

  

但是仍然不应该同时读取每个渲染的计数值。所以结果应该是

是的,但是您正在建立一个setInterval调用,该调用捕获计数器的值并每3秒重复一次setCounter(counter + 1)。因此,每3秒,计数器将重置为设置间隔加1时捕获的值。每次这样做,效果挂钩都会再次触发,并每3秒重复设置一个新的回调。

您是要使用setTimeout吗?

  useEffect(() => {
    setTimeout(() => {
      setCounter(counter+1)
    }, 3000)
  }, [counter]);

// Output: 1, 2, 3, 4, 5 ....

答案 1 :(得分:0)

要了解发生了什么,我在代码中添加了console.log个。如已接受的答案所解释

  

setInterval调用,捕获该计数器的值,并每3秒重复一次setCounter(counter + 1)。

为解决此问题,我在deps列表中添加了一个空数组以仅注册一次setInterval,并将回调传递给setCounter以捕获当前状态值

function App() {

  const [counter, setCounter] = useState(0);

  useEffect(() => {
    setInterval(() => {
      setCounter((storedCounter) => storedCounter+1 )
      console.log(counter, 'captured value')
    }, 3000)
  }, []);

  console.log(counter, ' state')


  return (
    <div>
      hi
    </div>
  );
}

export default App;

enter image description here