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

使用framer-motion的AnimatePresence时组件提前点击消失问题

问题原因

你的代码核心问题在于整个Component组件在状态切换时被直接卸载替换:

  • App组件中,boolean状态变化时会直接返回全新的Component实例,旧的Component会被立即销毁,其内部的AnimatePresence还没完成exit动画就跟着组件一起消失,导致h1元素直接从DOM中移除。
  • 你给AnimatePresence设置的mode="wait"只对其内部子元素的切换生效,但这里的问题是AnimatePresence本身被卸载了,所以这个配置无法发挥作用。
解决办法

有两种常见的修复思路,核心都是避免Component被直接卸载,或者让AnimatePresence管理组件的完整生命周期:

方案一:将AnimatePresence提升到App层,管理Component的切换

把AnimatePresence放到App组件中,给Component添加唯一key,让AnimatePresence负责旧组件的退出动画和新组件的进入动画:

import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";

export default function App() {
  const [boolean, setBoolean] = useState<boolean>(true);
  return (
    <AnimatePresence mode="wait">
      <Component 
        key={boolean ? "A" : "B"}
        text={boolean ? "A" : "B"} 
        onClick={() => setBoolean(!boolean)} 
      />
    </AnimatePresence>
  );
}

function Component({ text, onClick }: { text: string; onClick: () => void }) {
  return (
    <>
      <motion.h1
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
      >
        Title {text}
      </motion.h1>
      <button onClick={onClick}>Button {text}</button>
    </>
  );
}

方案二:将状态移到Component内部,避免组件卸载

把控制文本切换的状态放到Component组件内部,这样Component始终不会被卸载,只在内部通过key切换h1元素,让AnimatePresence管理h1的进出动画:

import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";

export default function App() {
  return <Component />;
}

function Component() {
  const [text, setText] = useState<string>("A");
  return (
    <>
      <AnimatePresence mode="wait">
        <motion.h1
          key={text}
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
        >
          Title {text}
        </motion.h1>
      </AnimatePresence>
      <button onClick={() => setText(text === "A" ? "B" : "A")}>
        Button {text}
      </button>
    </>
  );
}
效果说明

两种方案都能解决中途点击导致组件消失的问题:

  • 方案一中,AnimatePresence会等待旧Component的exit动画完成后,再挂载新的Component,确保动画过程中始终有元素存在。
  • 方案二中,Component保持挂载状态,AnimatePresence只处理h1元素的切换动画,即使中途点击,也只会触发新的动画队列,不会出现元素消失的情况。

内容的提问来源于stack exchange,提问作者Martí Serra Molina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:43:21