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

如何修改useEffect中setInterval的终止条件?适配Zustand动画场景

解决方案

核心问题是闭包捕获旧值导致定时器内无法获取最新的isHighlighted状态,确实需要用useRef来跟踪实时状态值。下面是修正后的完整实现:

关键思路

  1. 用useRef创建引用同步最新的isHighlighted状态,避开闭包陷阱
  2. 调整定时器逻辑:仅当isHighlighted变为false且当前动画周期结束时,才停止动画
  3. 增加清理逻辑,防止组件卸载时出现内存泄漏

修正后的代码

const animationPeriod_seconds = 1;
const [sustainAnimation, setSustainAnimation] = useState(false);
const isHighlighted = useEditorStore((state) =>
  state.highlightedSocketKeys.has(socketKey)
);

// 用ref跟踪最新的isHighlighted状态,避免闭包捕获旧值
const isHighlightedRef = useRef(isHighlighted);

// 同步ref与状态值
useEffect(() => {
  isHighlightedRef.current = isHighlighted;
}, [isHighlighted]);

useEffect(() => {
  let intervalId;

  if (isHighlighted) {
    // 激活状态下立即开启动画
    setSustainAnimation(true);

    intervalId = setInterval(() => {
      // 检查实时状态:如果已取消高亮,完成当前周期后停止动画
      if (!isHighlightedRef.current) {
        clearInterval(intervalId);
        setSustainAnimation(false);
      }
      // 若仍处于高亮状态,继续维持动画(无需额外操作)
    }, animationPeriod_seconds * 1000);
  }

  // 组件卸载或状态变化时清理定时器
  return () => {
    intervalId && clearInterval(intervalId);
  };
}, [isHighlighted]);

// 渲染时的动画判断条件
// {isHighlighted || sustainAnimation ? <你的脉冲动画组件 /> : null}

逻辑说明

  • isHighlightedRef会始终保存最新的状态值,定时器内通过isHighlightedRef.current可以获取实时状态,解决了闭包捕获旧值的问题
  • 当isHighlighted激活时,立即启动动画和周期检查;每个周期结束后,若状态仍为true则继续维持动画,若已变为false则清理定时器并关闭动画,确保完成当前完整周期
  • 清理函数会在组件卸载或isHighlighted变化时清除定时器,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 12:07:25