如何将旧版AnimatePresence代码转换适配至Next.js 13版本?
Next.js 13 App Router 适配 Framer Motion AnimatePresence 方案
原 Next.js Pages Router 中 _app.js 的全局 AnimatePresence 用法,在 App Router 下需要调整为客户端组件包裹+页面级动画配置的模式,具体步骤如下:
1. 创建全局 AnimatePresence 客户端包裹组件
由于 Framer Motion 依赖客户端交互,需给组件添加 'use client' 指令,将其作为全局动画容器:
// app/components/AnimatePresenceWrapper.jsx 'use client'; import { AnimatePresence } from 'framer-motion'; export default function AnimatePresenceWrapper({ children }) { return ( <AnimatePresence mode="wait" initial={false}> {children} </AnimatePresence> ); }
2. 在根布局中引入该包裹组件
将根布局 layout.js 中的页面内容用上述组件包裹,实现全局动画上下文:
// app/layout.js import AnimatePresenceWrapper from './components/AnimatePresenceWrapper'; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body> <AnimatePresenceWrapper>{children}</AnimatePresenceWrapper> </body> </html> ); }
3. 给单个页面添加动画配置
每个页面组件需要用 motion 容器包裹,并设置唯一的 key(推荐用当前路由路径),同时配置入场/退场动画:
// app/about/page.jsx 'use client'; import { motion } from 'framer-motion'; import { usePathname } from 'next/navigation'; export default function AboutPage() { const pathname = usePathname(); // 获取当前路由路径作为唯一key return ( <motion.div key={pathname} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -20 }} transition={{ duration: 0.5 }} > <h1>关于页面</h1> {/* 页面内容 */} </motion.div> ); }
注意事项
- 所有使用 Framer Motion 的组件(包括包裹组件和页面组件)都必须添加
'use client'指令,避免服务器端渲染报错。 AnimatePresence的mode="wait"配置会等待上一个页面的退场动画完成后再播放新页面的入场动画,保持和原代码一致的行为。- 若需更精细的路由动画控制,可结合
useRouter钩子监听路由变化,自定义动画触发逻辑。
内容的提问来源于stack exchange,提问作者Tabim
相关产品推荐
相关产品推荐

