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

InView组件回调触发时AnimatedText动画重置问题排查

排查思路与解决方案

1. 核心问题:组件重复挂载导致动画重置

你的AnimatedText组件中,ComposeTag和ComposeMotion是在组件函数内部定义的:

const ComposeTag = ({ children }: ComposeTagProps) => {
  return React.createElement(as, { className, id }, children);
};

const ComposeMotion = motion(ComposeTag);

每次AnimatedText重渲染时,这两个都会被重新创建,React会判定这是全新的组件类型,进而卸载旧实例、挂载新实例——这直接导致motion.span的动画状态被重置回initial配置。

解决方法:将组件定义移到外部或用useMemo缓存:

// 移到AnimatedText组件外部
const ComposeTag = React.memo(({ as, className, id, children }: ComposeTagProps & {as: TextElements, className?: string, id?: string}) => {
  return React.createElement(as, { className, id }, children);
});

export const AnimatedText = ({
  as = 'h1',
  className,
  children,
  auto = true,
  id,
}: AnimatedTextProps) => {
  const textArr = children.split(' ');
  // 缓存motion包装后的组件,避免重复创建
  const ComposeMotion = useMemo(() => motion(ComposeTag), []);

  // ... 其余代码不变
};

2. 优化不必要的重渲染

父组件Home中darkNavbar状态更新时,会触发整个组件重渲染,连带所有子组件(包括AnimatedText)也重渲染,会放大上述挂载问题。

优化点:

  • 给AnimatedText添加React.memo,避免props未变化时的无意义重渲染:
    export const AnimatedText = React.memo(({
      as = 'h1',
      className,
      children,
      auto = true,
      id,
    }: AnimatedTextProps) => {
      // ... 组件内部代码
    });
    
  • 检查Navbar是否依赖darkNavbar状态,如果是,确保Navbar的重渲染不会向上扩散(比如用context时限制更新范围)。

3. 验证组件挂载状态

可以在AnimatedText中添加日志,确认组件是重渲染还是卸载再挂载:

useEffect(() => {
  console.log('AnimatedText 挂载');
  return () => console.log('AnimatedText 卸载');
}, []);

如果每次darkNavbar变化时都打印卸载/挂载日志,说明就是组件重复挂载导致的问题,回到第1点的解决方案即可。

4. 确认framer-motion动画逻辑

AnimatedText中同时使用了useAnimate和motion.span的initial属性,正常情况下framer-motion会保留组件重渲染时的动画状态,但如果组件被卸载再挂载,就会重置到初始状态。

另外,注意auto=false的AnimatedText(比如hero区域的文本),要确保它的动画是通过useMotionTimeline控制,不会被useInView的逻辑干扰。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 05:30:58