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

useEffect内更新状态未按预期多次重渲染且定时器失效问题求助

useEffect内更新状态未按预期多次重渲染且定时器失效问题求助

Hey there! Let's break down what's going wrong here and how to fix it. You're hitting a couple of common JavaScript closure pitfalls plus a state management oversight—let's tackle them one by one.

问题根源分析

  1. 闭包导致的变量引用问题:
    你的newDef变量声明在for循环外部,所有setTimeout回调都会捕获同一个newDef引用。当1秒后定时器触发时,循环已经跑完了150次,newDef早就被更新成最后一次循环的结果,所以状态只会被设置为最后那个值。

  2. 定时器未错开执行时机:
    所有定时器都被设置为1000ms后触发,它们会在同一时间点集中执行,看起来就像是状态瞬间更新,而不是逐步变化。

  3. startAnimationFinished不是状态变量:
    你直接修改了一个普通变量,但它会在每次组件渲染时重置初始值。如果pathIsActive再次变化,动画可能会意外重复执行。

修复方案

下面是调整后的代码,解决了上述所有问题:

const [definition, setDefinition] = useState('');
// 将startAnimationFinished改为状态变量,确保跨渲染持久化
const [startAnimationFinished, setStartAnimationFinished] = useState(false);

useEffect(() => {
  if (startAnimationFinished) return;
  if (!pathIsActive) return;

  // 存储定时器ID,方便后续清理
  const timeoutIds = [];

  for (let i = 0; i < 150; i++) {
    // 把newDef放到循环内部,让每个迭代都有独立的变量引用
    const newDef = `M ${i} ${i} L ${i} ${i}`;
    // 通过索引错开定时器触发时间(这里用50ms间隔,可根据需求调整)
    const id = setTimeout(() => {
      setDefinition(newDef);
    }, 50 * i);
    timeoutIds.push(id);
  }

  // 使用状态更新器修改startAnimationFinished
  setStartAnimationFinished(true);

  // 清理函数:组件卸载或依赖变化时,清除未执行的定时器
  return () => {
    timeoutIds.forEach(id => clearTimeout(id));
  };
}, [pathIsActive, startAnimationFinished]); // 把startAnimationFinished加入依赖数组

return (
  <>
    <svg
      className={'path' + (pathIsActive ? ' active' : '')}
      xmlns="http://www.w3.org/2000/svg"
      style={{ border: '1px solid blue' }}
      viewBox={`${-width / 4} ${-width / 4} ${width} ${width}`}
      {...props}
    >
      <path fill='none' stroke="white" width='1'
        style={{ filter: "drop-shadow(0px 0px 5px white)" }}
        d={definition}
      />
    </svg>
  </>
);

额外优化提示

如果想要更流畅的动画效果,可以考虑用requestAnimationFrame替代setTimeout,它会和浏览器的刷新频率同步,减少卡顿感。不过上面的修改已经能解决你当前遇到的核心问题啦。

备注:内容来源于stack exchange,提问作者PRR S2 6-8-6 turbine engine

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 15:27:43