React useState()引发无关组件异常:GSAP动画停止问题
GSAP无限动画在父组件状态更新后停止的解决方案
问题原因
当父组件通过useState更新状态时,即便没有向子组件传递任何props,React默认会触发所有子组件的重渲染。如果你的GSAP动画是在组件挂载阶段初始化的(比如依赖项为空的useEffect),旧组件实例卸载时会销毁对应的GSAP动画实例,而新组件实例若未重新启动动画,就会出现动画停止的情况。
解决方案
1. 用React.memo避免子组件不必要重渲染
将子组件用React.memo包裹,让它仅在props发生变化时才重渲染。由于你的子组件不依赖父组件props,这能直接阻断父组件状态更新带来的子组件重渲染。
示例代码:
import React, { memo } from 'react'; import gsap from 'gsap'; const AnimatedComponent = memo(() => { const elementRef = React.useRef(null); React.useEffect(() => { gsap.timeline({ repeat: -1 }) .to(elementRef.current, { x: 200, duration: 1 }) .to(elementRef.current, { x: 0, duration: 1 }); }, []); return <div ref={elementRef} className="box"></div>; }); export default AnimatedComponent;
2. 用useRef保留动画实例并正确清理
如果子组件确实需要重渲染,可通过useRef存储GSAP时间线实例,确保组件重渲染时不会重复创建新动画,同时在组件卸载时清理动画避免内存泄漏。
示例代码:
import React, { useEffect, useRef } from 'react'; import gsap from 'gsap'; const AnimatedComponent = () => { const elementRef = useRef(null); const timelineRef = useRef(null); useEffect(() => { // 仅在实例不存在时创建动画 if (!timelineRef.current) { timelineRef.current = gsap.timeline({ repeat: -1 }) .to(elementRef.current, { x: 200, duration: 1 }) .to(elementRef.current, { x: 0, duration: 1 }); } // 组件卸载时清理动画 return () => { if (timelineRef.current) { timelineRef.current.kill(); timelineRef.current = null; } }; }, []); return <div ref={elementRef} className="box"></div>; }; export default AnimatedComponent;
内容的提问来源于stack exchange,提问作者Marcelo Velasquez
相关产品推荐
相关产品推荐

