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

Framer Motion退出动画失效求助:切换视图时元素直接消失

解决Framer Motion退出动画不生效的问题

问题出在哪

  1. AnimatePresence放错位置:你把AnimatePresence嵌套在HomePage组件内部,切换页面卸载HomePage时,AnimatePresence会跟着被卸载,根本没机会执行exit动画。
  2. 根动画元素缺少唯一key:AnimatePresence依赖key识别组件的挂载/卸载状态,你HomePage里最外层的motion.div没设置唯一key,它无法判断组件要执行卸载动画。
  3. 动画属性冲突:比如comments_container同时应用slideAnimation("down")和fadeAnimation时,后者的exit属性会覆盖前者,导致退出动画不符合预期甚至失效。

修复步骤

1. 迁移AnimatePresence到路由父组件

AnimatePresence需要包裹所有可能切换的页面组件,比如放在路由配置的入口处:

// 路由入口组件示例
import { AnimatePresence } from "framer-motion";
import { Routes, Route, useLocation } from "react-router-dom";
import HomePage from "./HomePage";
import OtherPage from "./OtherPage";

const AppRouter = () => {
  const location = useLocation();
  return (
    <AnimatePresence mode="wait">
      <Routes location={location} key={location.pathname}>
        <Route path="/" element={<HomePage />} />
        <Route path="/other" element={<OtherPage />} />
      </Routes>
    </AnimatePresence>
  );
};

加mode="wait"是为了等待退出动画完成后,再加载新页面的入场动画;给Routes设置key={location.pathname},让AnimatePresence能感知路由切换。

2. 给HomePage根motion元素添加唯一key

删除HomePage内部的AnimatePresence,给最外层motion.div设置唯一标识:

// 修改后的HomePage组件
const HomePage = () => {
  return (
    <motion.div className="card" key="home-page"> {/* 添加唯一key */}
      <motion.div className="card_section1" {...slideAnimation("left")} key="custom">
        <h2 className="title_name">text</h2>
        <motion.h3 className="subtitle" {...slideAnimation("left")} key="custom2">
          {" "}
          {">"} Front-End Developer
        </motion.h3>
        <motion.div
          className="comments_container"
          key="custom3"
          // 手动合并动画属性,避免exit被覆盖
          initial={{ ...slideAnimation("down").initial, ...fadeAnimation.initial }}
          animate={{ ...slideAnimation("down").animate, ...fadeAnimation.animate }}
          exit={{ ...slideAnimation("down").exit, ...fadeAnimation.exit }}
          transition={{ ...transition }}
        >
          <h6 className="comment">{"//"} explore my projects</h6>
          <h6 className="comment">
            {"//"} you can also see it on my Github page
          </h6>
          <h6 className="github">
            <span style={{ color: "#4D5BCE" }}>const</span> {" "}
            <span style={{ color: "#43D9AD" }}>githubLink</span>
            <span style={{ color: "white" }}> = </span>
            <a style={{ color: "#E99287" }} href={githubUrl} target="_blank" rel="noreferrer">
              text
            </a>
          </h6>
        </motion.div>
      </motion.div>
      <motion.div className="card_section2" {...slideAnimation("left")} key="custom4">
        <h3>Main Tecnologies</h3>
        <motion.div className="technologies_image" {...fadeAnimation} key="tech-images">
          {Images.map((image, i) => {
            return <img key={i} src={image} alt={image} />;
          })}
        </motion.div>
      </motion.div>
    </motion.div>
  );
};

3. 修复动画属性冲突

同时应用多个动画对象时,直接展开会覆盖同名属性,需要手动合并initial、animate、exit状态,确保所有动画效果都能生效(如上面的comments_container组件)。

额外提醒

  • AnimatePresence必须在要卸载的组件外层,不能和组件同时被卸载。
  • 每个motion元素的key要唯一,避免用随机值或列表索引作为关键元素的key。
  • 使用React Router v6时,必须给Routes传递location和key属性,否则AnimatePresence无法检测路由变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:49:54