You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React useEffect Hook异常:无清理函数时定时器计数器运行到10卡顿停止

异常发生的原因

你的代码运行出现卡顿停止的核心问题是定时器泄漏+闭包陷阱,具体执行逻辑如下:

  • useEffect的依赖项设置为count,意味着每次count值更新时,整个useEffect回调都会重新执行一次
  • 你注释了定时器清理逻辑,上一次useEffect执行创建的定时器不会被销毁,会一直驻留在内存中运行
  • 每个定时器都捕获了创建时对应渲染闭包内的count固定值,比如首次渲染创建的定时器永远只会执行setCount(0 + 1),第二次渲染创建的定时器永远只会执行setCount(1 + 1),以此类推
  • 随着count值上涨,后台并行运行的定时器数量会线性增长,运行几秒后就会有数十个定时器同时触发:一方面大量定时器占用JS线程资源导致页面卡顿,另一方面大量重复的setState调用触发频繁重渲染,最终会阻塞JS线程,导致计数器停止更新。

添加清理函数后恢复正常的原因

当你放开注释的清理函数逻辑后:

  • 每次useEffect重新执行前,都会先触发上一次useEffect返回的清理函数,把前一个旧定时器销毁,全程只会有1个定时器在后台运行
  • 每次新创建的定时器捕获的是当前最新的count值,所以会按预期每秒执行一次自增逻辑,计数器自然就正常运行了。

更优的实现方案

你可以用setState的函数式更新写法,不需要把count加入useEffect依赖,也不用频繁销毁重建定时器,性能更好:

import { useState, useEffect } from "react";

function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      // 函数式更新可以直接拿到上一轮的最新state值,不需要依赖外部count变量
      setCount(prevCount => prevCount + 1);
    }, 1000);
    return () => clearInterval(interval);
  }, []); // 空依赖,useEffect只会在组件挂载时执行一次

  return (
    <div className="App">
      <h1>{count}</h1>
    </div>
  );
}

export default App;

内容的提问来源于stack exchange,提问作者Abhinav Dhiman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:24:05