Framer Motion退出动画失效排查(基于React与Animate Presence)
问题原因及解决方案:Framer Motion AnimatePresence 退出动画不触发
核心问题分析
你的代码存在两个关键错误,直接导致退出动画无法正常运行:
AnimatePresence 被包裹在条件渲染内部
当show变为false时,AnimatePresence组件本身会被立即卸载,它根本没有机会监听内部motion组件的卸载过程,自然无法触发退出动画。AnimatePresence必须始终存在于DOM中,才能追踪子组件的挂载/卸载状态。退出动画的目标状态无效
你设置的exit={{ opacity: 1, transition: { duration: 1 } }}没有任何视觉变化(初始与退出状态的opacity一致),即使动画运行了也无法被察觉。
修正后的代码示例
import React from "react"; import { useState } from "react"; import { AnimatePresence, motion } from "framer-motion"; export default function NotExit() { const [show, toggle] = useState(true); const MyComponent = ({ isVisible }) => ( // AnimatePresence 放在条件渲染外部 <AnimatePresence> {isVisible && ( <motion.div key="modal" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0, transition: { duration: 1 } }} style={{ width: 100, height: 100, backgroundColor: "blue" }} /> )} </AnimatePresence> ); return ( <div className="relative w-screen h-screen flex flex-col-reverse justify-center items-center"> <button className="bg-purple-600 p-2 rounded text-white" onClick={() => toggle(!show)} > 切换显示 </button> // 把 AnimatePresence 移到条件渲染外面 <AnimatePresence mode="wait"> {show && ( <motion.section key="cock" initial={{ y: 100, opacity: 0 }} animate={{ y: 0, opacity: 1 }} exit={{ y: 100, opacity: 0, transition: { duration: 1 } }} className="w-44 h-44 bg-red-500 rounded-xl" transition={{ duration: 1 }} /> )} </AnimatePresence> </div> ); }
关键修复点说明
- 调整AnimatePresence的位置:确保它始终处于DOM中,只让内部的
motion组件进行条件渲染。这样AnimatePresence才能捕获到子组件的卸载事件,触发exit动画。 - 修正exit动画状态:设置与初始状态对应的退出目标(比如初始
y:100,退出也设y:100;初始opacity:0,退出设opacity:0),让动画有明显的视觉变化。 - 保留
mode="wait"(可选):如果需要等待退出动画完成后再卸载组件,mode="wait"可以确保动画执行完毕后再移除DOM元素,避免动画被中断。
内容的提问来源于stack exchange,提问作者ayman dev
相关产品推荐
相关产品推荐

