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

Javascript 在useEffect中调用setInterval时会发生什么,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我有以下反应成分 function App() { const [counter, setCounter] = useState(0); useEffect(() => { setInterval(() => { setCounter(counter+1) }, 3000) }, [counter]); console.log(counter) return ( <div> hi &

我有以下反应成分

function App() {

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

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

  console.log(counter)

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

export default App;
函数应用程序(){
const[counter,setCounter]=useState(0);
useffect(()=>{
设置间隔(()=>{
设置计数器(计数器+1)
}, 3000)
},[柜台];
控制台日志(计数器)
返回(
你好
);
}
导出默认应用程序;
我得到的结果是

0

一,

一,

二,

一,

二,

三,

我知道,每次调用setCounter时,组件都会被重新渲染,每次渲染时,useffect回调都会被重新创建。我的问题是,不应该通过结果读取每次渲染的计数值

1、2、3、4、5

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

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

您的意思是使用
setTimeout

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

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

为了了解发生了什么,我在代码中添加了一些
console.log
。正如公认的答案所解释的那样

setInterval调用,该调用捕获计数器的值,并每3秒重复一次setCounter(计数器+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;
函数应用程序(){
const[counter,setCounter]=useState(0);
useffect(()=>{
设置间隔(()=>{
setCounter((storedCounter)=>storedCounter+1)
console.log(计数器“捕获值”)
}, 3000)
}, []);
console.log(计数器“state”)
返回(
你好
);
}
导出默认应用程序;

您从未取消之前设置的间隔;随着时间的推移,有越来越多的计数器关闭不同的值。谢谢,我现在明白了。实际上,我想设置间隔,我应该从deps列表中省略计数器,使其只运行一次。我更新了我的代码,使其具有很少的控制台日志,以查看发生了什么。在发布问题之前应该这样做:)无论如何,我发布了解决问题的方式作为答案。这可能比至少每3秒钟运行一次钩子更有效。