使用React HOC与AnimatePresence时Framer Motion退出动画不生效
解决React动画HOC中AnimatePresence退出动画不执行的问题
问题根源
- 组件类型不稳定:你在主组件内部每次渲染时都重新创建
InfoWithDropDown组件(const InfoWithDropDown = withDropdown(someInfo);),导致React每次都会卸载旧组件、挂载新组件,而非更新现有组件。AnimatePresence无法跟踪这种强制卸载行为,自然不会触发退出动画。 - 动画配置逻辑冲突:
motion.div的initial和animate都设置为height: "auto",初始状态与动画状态完全一致,无法触发正确的入场/退出动画流程。
修复步骤
1. 稳定HOC生成的组件类型
将HOC的调用移到主组件外部,确保组件类型在渲染周期中保持稳定:
// 移到主组件外部,只执行一次 const InfoWithDropDown = withDropdown(someInfo); const MainComponent = () => { const [showThis, setShowThis] = useState(false); return ( <InfoWithDropDown collapsed={showThis} collapsedSetter={setShowThis} /> ); };
2. 调整motion动画配置
修改motion.div的动画参数,让入场和退出状态形成有效过渡,同时确保motion能正确计算高度变化:
const withDropdown = (Component: React.ComponentType) => (props: InfoProps) => ( <div className=""> <button onClick={() => props.collapsedSetter(!props.collapsed)}> {props.collapsed ? '收起' : '展开'} </button> <AnimatePresence> {props.collapsed && ( <motion.div key="dropdown-content" className="overflow-hidden" initial={{ height: 0 }} animate={{ height: "auto" }} exit={{ height: 0 }} transition={{ duration: 0.3 }} > <Component /> </motion.div> )} </AnimatePresence> </div> );
- 把
initial设为height: 0,让入场动画从0过渡到auto - 添加
transition明确动画时长,提升效果可控性 - 补全按钮的点击逻辑,正确切换
collapsed状态
3. 可选优化:使用layout属性处理高度动画
如果height: auto的动画仍有问题,可以尝试用motion的layout属性自动处理尺寸变化:
<motion.div key="dropdown-content" className="overflow-hidden" initial={{ opacity: 0, height: 0 }} animate={{ opacity: 1, height: "auto" }} exit={{ opacity: 0, height: 0 }} layout transition={{ duration: 0.3 }} > <Component /> </motion.div>
layout属性会让motion自动计算元素的自然尺寸,避免手动设置height可能带来的兼容性问题。
验证要点
- 确保
AnimatePresence的直接子元素是条件渲染的motion组件,且拥有唯一稳定的key - 组件类型必须稳定,不能在渲染函数内部动态生成HOC组件
- 动画的初始、目标状态必须存在差异,才能触发过渡效果
内容的提问来源于stack exchange,提问作者Pajke
相关产品推荐
相关产品推荐

