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

React中useEffect与setInterval实现计时器引发无限渲染问题求助

计时器无限重复渲染问题分析与修复

核心问题原因

1. useEffect未设置依赖数组且未清理定时器

你代码中的两个useEffect都存在致命问题:

  • 没有指定依赖数组,导致组件每次渲染都会重新执行useEffect逻辑,重复创建新的定时器,旧定时器未被清除,多个定时器同时触发状态更新,引发频繁渲染循环。
  • 缺少定时器清理逻辑,组件卸载或状态变更时,旧定时器仍在后台运行,持续触发状态更新。

2. 定时器闭包捕获旧状态值

Activity.js中定时器的回调直接使用cooldownDuration,由于闭包特性,它捕获的是初始渲染时的状态值,后续每次执行都是用旧值减1000,无法正确更新状态,同时会触发无效的状态更新,加剧渲染循环。

修复方案

1. 修复Activity.js中的useEffect

useEffect(() => {
  let interval;
  if (props.activity.cooldown && cooldownDuration > 0) {
    if (props.activity.id === 1) {
      console.log('Activity.js state', cooldownDuration);
    }
    // 使用函数式更新获取最新状态值
    interval = setInterval(() => {
      setCooldownDuration(prev => prev - 1000);
    }, 1000);
  } else {
    setCooldownDuration(0);
  }

  // 清理函数:组件卸载或依赖变更时清除定时器
  return () => clearInterval(interval);
}, [props.activity.cooldown, cooldownDuration]); // 添加依赖数组,仅在依赖变更时执行

2. 修复ActivityProgression.js中的useEffect

useEffect(() => {
  const calculatePercentage = () => {
    const percentage = ((props.totalTime - props.cooldown) / props.totalTime) * 100;
    setPercentages(percentage);
  };

  calculatePercentage();
  // 保留定时器的同时添加清理逻辑
  const interval = setInterval(calculatePercentage, 1000);

  return () => clearInterval(interval);
}, [props.totalTime, props.cooldown]); // 添加依赖数组

额外优化建议

进度条的百分比可以直接在渲染时计算,无需用状态存储,减少不必要的状态更新:

return (
  <ProgressBar 
    animated 
    now={((props.totalTime - props.cooldown) / props.totalTime) * 100} 
    label={`${Math.round(((props.totalTime - props.cooldown) / props.totalTime) * 100)}%`} 
  />
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 06:35:48