reactjs React自增量计时器

z4bn682m  于 5个月前  发布在  React
关注(0)|答案(1)|浏览(64)

我想在页面加载时启动一个计时器,我的代码如下:

function App() {
     const [sec, setSec] = useState(0);

     useEffect(()=>{
      setInterval(()=>{setSec(prev=>prev+1)
      }, 1000)}, [sec])

  return (
    <span>{sec}</span>
  )}

字符串
但是计数器的增量不是每秒钟,而是非常快。我不知道问题是什么。
我认为setInterval()将每秒运行一次,这会更新sec变量,而sec变量又会调用useEffect()中的回调函数,以便它可以再次运行。
我确实在网上找到了一些设置react计时器的示例代码,但是他们使用useRef()来保存setInterval()回调函数,然后更新sec变量,比如setSec(sec+1)。我粗略地理解了其中的逻辑,但并不完全理解,我不明白为什么我的代码不起作用。
如果有人能帮助我,非常感谢。如果我错过了一些简单的事情,我很抱歉。

8e2ybdfx

8e2ybdfx1#

我看到两个问题。
首先,从useEffect的依赖数组中删除sec。你应该使用一个间隔 * 或 * 作为效果依赖,但不能同时使用。当你同时使用这两种方法时,你实际上是在每次重新渲染时创建一个新的间隔,所以每次重新渲染都会增加增量的数量,并且速率将无限地复合。
如果你想依赖数组和在每个渲染上重新运行的效果,你只需要使用setTimeout而不是setInterval。例如:

useEffect(() => {
  setTimeout(() => {
    setSec((prev) => prev + 1);
  }, 1000);
}, [sec]);

字符串
这样,组件的每次重新渲染(以及效果的每次重新调用)只执行一个增量,而不是增量集的新的持续间隔。
第二,也是更微妙的一点,这种影响会留下一个没有被清除的副作用。如果组件在技术上渲染两次,这在开发环境中会很明显,并且你会看到你的计数器每秒增加2而不是1。
你可以通过从useEffect回调中返回一个cleanup函数来“清理”一个效果。当组件卸载时,React会使用这个函数。例如:

useEffect(() => {
  const x = setInterval(() => {
    setSec((prev) => prev + 1);
  }, 1000);

  // return a cleanup function here
  return () => clearInterval(x);
}, []);

相关问题