Framer-motion退出条件未正确生效问题排查
Framer-motion Exit动画未触发,元素仅隐藏未从DOM移除的解决方案
你的问题核心在于AnimatePresence的exit动画只有当motion组件被从DOM中卸载时才会触发,而原代码中所有卡片始终挂载在DOM里,只是通过animate切换opacity,完全不会触发exit逻辑——哪怕设置了exit={{display: "none"}}也没用,而且display属性本身无法被Framer-motion做过渡动画。
解决步骤:
- 条件渲染控制DOM挂载:只有选中的卡片保留在DOM中,未选中的直接不渲染(从DOM移除),让AnimatePresence能检测到元素的卸载动作。
- 调整exit动画属性:使用可动画的属性(如opacity、height、padding)完成淡出/收缩效果,动画结束后元素自然从DOM消失。
修改后的代码示例:
import "./styles.css"; import { useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; export default function App() { const [selectedCard, setSelectedCard] = useState(null); const cards = ["Card 1", "Card 2", "Card 3"]; return ( <AnimatePresence> <div className="cards"> {cards.map((card, index) => { // 当选中状态存在时,仅渲染选中的卡片 if (selectedCard !== null && selectedCard !== index) return null; return ( <motion.div className="card" key={index} onClick={() => setSelectedCard(selectedCard === index ? null : index)} initial={{ opacity: 1, height: "auto", padding: "1rem" }} exit={{ opacity: 0, height: 0, padding: 0, transition: { duration: 0.5 } }} > {card} </motion.div> ); })} </div> </AnimatePresence> ); }
关键说明:
- 当点击卡片后,未选中的卡片通过条件渲染被排除在DOM之外,AnimatePresence会自动触发它们的exit动画。
- exit动画中加入
height: 0和padding: 0,是为了让元素在淡出的同时收缩,避免布局出现跳动;动画结束后元素直接从DOM移除,完全符合你的需求。 - 如果不需要收缩效果,仅保留
opacity: 0的exit动画即可,元素会在淡出后被移除。
内容的提问来源于stack exchange,提问作者Gabi
相关产品推荐
相关产品推荐

