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

Next.js 13.4(App Router)中AnimatePresence的正确放置位置

在Next.js 13.4 App Router中正确使用Framer Motion的AnimatePresence

你之前的写法无法生效主要有两个核心原因:一是RootLayout默认是服务器组件,不能直接使用Framer Motion这类客户端组件;二是App Router下无法直接给children添加key来触发AnimatePresence的路由变化检测。以下是可行的解决方案:

步骤1:创建客户端动画布局组件

新建一个带'use client'指令的组件,专门处理AnimatePresence的包裹逻辑:

'use client';

import { AnimatePresence } from 'framer-motion';
import { usePathname } from 'next/navigation';

export default function AnimatedLayout({ children }: { children: React.ReactNode }) {
  // 用App Router的usePathname获取当前路由路径,替代旧版的router.asPath
  const pathname = usePathname();

  return (
    // initial={false} 保持和旧版一致,避免初始加载触发动画
    // mode="wait" 确保退出动画完成后再渲染新页面
    <AnimatePresence initial={false} mode="wait">
      {/* 用当前路径作为key,让AnimatePresence识别路由变化 */}
      <div key={pathname}>{children}</div>
    </AnimatePresence>
  );
}

步骤2:修改RootLayout使用动画组件

在RootLayout中引入刚才创建的AnimatedLayout,用它包裹路由内容:

import AnimatedLayout from './AnimatedLayout';
import Footer from './Footer';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <link
          rel="stylesheet"
          href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@48,400,1,0"
        />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
      </head>
      <body>
        {/* 用AnimatedLayout替代直接包裹children */}
        <AnimatedLayout>{children}</AnimatedLayout>
        
        <div className="container__small">
          <Footer />
        </div>
      </body>
    </html>
  );
}

步骤3:给页面组件添加动画属性

确保每个页面组件(放在app/下的路由组件)使用motion组件,并设置initial、animate、exit动画参数:

'use client';

import { motion } from 'framer-motion';

export default function Home() {
  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -20 }}
      transition={{ duration: 0.3 }}
    >
      <h1>首页内容</h1>
    </motion.div>
  );
}

关键说明

  • 'use client'指令是必须的:Framer Motion的组件依赖客户端环境,所以包裹AnimatePresence的组件必须声明为客户端组件。
  • usePathname的作用:替代旧版useRouter的asPath,用来标识当前路由,让AnimatePresence能检测到页面切换。
  • mode="wait":防止新页面提前渲染导致的视觉冲突,保证退出动画完成后再显示新页面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 20:38:12