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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:35:00