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

如何使用Framer Motion在每次状态变更时重新触发动画

问题根因

Framer Motion 默认仅在animate、variants等动画配置属性发生变更时才会触发新的动画过渡,你当前代码中initial="hide"和animate="show"在组件首次挂载后就没有发生过变化,因此即便组件因为state更新重渲染,也不会重新执行入场动画。

解决方案

方案1:绑定动态key(最适配当前场景,修改成本最低)

给motion组件添加key属性,值绑定到你每次会更新的state变量。React在检测到key值变化时,会销毁旧的组件实例、重新挂载新实例,自然会重新触发从hide到show的完整动画流程。
修改后的完整代码如下:

import React, { useEffect, useState } from "react";
import { motion} from "framer-motion";
import styled from "styled-components";

const Screen = () => {
  const [state, setState] = useState(1);

  useEffect(() => {
    setInterval(() => {
      setState(Math.random());
    }, 4000);
  }, []);

  return (
    {/* 仅新增了key={state}这一行配置 */}
    <Title key={state} variants={variants} animate="show" initial="hide">
      {console.log("re-render")}
      {`screen ${state}`}
    </Title>
  );
};

const Title = styled(motion.div)`
  color: red;
`;

export const variants = {
  show: {
    opacity: 1,
    y: 0,
    transition: {
      ease: "easeOut",
      duration: 0.3
    }
  },
  hide: {
    y: -20,
    opacity: 0
  }
};

export default Screen;

方案2:使用useAnimation钩子手动控制

如果不想频繁销毁重建组件,可以使用useAnimation钩子手动控制动画播放时机,监听state变化后主动触发动画重置和播放:

import React, { useEffect, useState } from "react";
import { motion, useAnimation } from "framer-motion";
import styled from "styled-components";

const Screen = () => {
  const [state, setState] = useState(1);
  const controls = useAnimation();

  useEffect(() => {
    setInterval(() => {
      setState(Math.random());
    }, 4000);
  }, []);

  // 监听state变化,每次变更时先重置到隐藏状态,再播放显示动画
  useEffect(() => {
    controls.start("hide").then(() => {
      controls.start("show");
    });
  }, [state, controls]);

  return (
    <Title variants={variants} animate={controls} initial="hide">
      {console.log("re-render")}
      {`screen ${state}`}
    </Title>
  );
};

const Title = styled(motion.div)`
  color: red;
`;

export const variants = {
  show: {
    opacity: 1,
    y: 0,
    transition: {
      ease: "easeOut",
      duration: 0.3
    }
  },
  hide: {
    y: -20,
    opacity: 0,
    // 隐藏动画设置为0时长,无过渡直接跳转状态
    transition: { duration: 0 }
  }
};

export default Screen;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:18:04