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

如何停止定义在useEffect外部的setInterval 解决React进度条更新异常问题

问题根因
  • 定时器创建位置错误:setInterval直接写在组件顶层,每次状态更新触发组件重渲染时都会生成新的定时器,多个定时器并行运行导致状态更新异常
  • 闭包陷阱:定时器回调中读取的percentage是初始化时的静态值,不会跟随状态更新变化,数值累加逻辑不符合预期
  • 定时器ID无法共享:每次重渲染都会重新声明progressInterval变量,判断条件中拿到的不是当前运行的定时器ID,导致clearInterval无法生效
  • 时间配置不符需求:原代码定时器间隔写为10000(10秒),和要求的5秒递增不符
修复后完整代码
import {useState, useEffect, useRef} from 'react';

function App() {
  const [percentage,setPercentage] = useState(99)
  // 用ref存储定时器ID,全渲染周期共享
  const progressIntervalRef = useRef(null)

  // 仅组件首次挂载时创建一次定时器
  useEffect(() => {
    progressIntervalRef.current = setInterval(()=>{
      // 函数式更新状态,避开闭包陷阱
      setPercentage(prev => prev + 1);
    },5000);
    // 组件卸载时自动清理定时器,避免内存泄漏
    return () => clearInterval(progressIntervalRef.current)
  }, [])

  useEffect(() => {
    if(percentage === 100) {
      console.log("completed");
      clearInterval(progressIntervalRef.current);
    }
  }, [percentage])

  const progress = {
    backgroundColor: 'yellow',
    width: `${percentage}%`,
    textAlign: 'right',
  }
  const fullWidth = {
    border: '1px solid black',
    backgroundColor: '#eff',
    margin: '10px'
  }

  return (
    <>
      <div style={fullWidth}>
        <div style={progress}>{percentage}%</div>
      </div>
    </>
  );
}

export default App;
核心修改说明
  • 新增useRef存储定时器ID,保证所有渲染过程中读取的是同一个定时器实例,可正常清除
  • 将定时器创建逻辑移入仅执行一次的useEffect中,避免重复生成多个定时器
  • 状态更新改用函数式写法,直接读取上一次的最新状态,避开闭包导致的旧值问题
  • 增加组件卸载时的定时器清理逻辑,避免内存泄漏
  • 将定时器间隔调整为5000,匹配5秒递增的需求

内容的提问来源于stack exchange,提问作者vivek modi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:06:03