如何修改useEffect中setInterval的终止条件?适配Zustand动画场景
解决方案
核心问题是闭包捕获旧值导致定时器内无法获取最新的isHighlighted状态,确实需要用useRef来跟踪实时状态值。下面是修正后的完整实现:
关键思路
- 用
useRef创建引用同步最新的isHighlighted状态,避开闭包陷阱 - 调整定时器逻辑:仅当
isHighlighted变为false且当前动画周期结束时,才停止动画 - 增加清理逻辑,防止组件卸载时出现内存泄漏
修正后的代码
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
相关产品推荐
相关产品推荐

