Next.js 13.4.19中Framer Motion动画无法正常工作的问题
解决Next.js 13.4.19中Framer Motion动画不生效的问题
你的动画未生效主要有两个核心原因:Framer Motion的exit动画必须依赖AnimatePresence组件触发,以及Next.js App Router的服务器渲染特性可能影响初始动画的执行。以下是具体解决方案:
1. 用AnimatePresence包裹组件以启用exit动画
exit属性只有在组件被AnimatePresence直接包裹,且组件拥有唯一key时才会触发。你当前的代码缺少这一层包裹,所以退出动画完全不会运行。
方案1:将page.js转为客户端组件
直接修改page.js,添加"use client"指令并引入AnimatePresence:
"use client"; import { AnimatePresence } from "framer-motion"; import Navbar from "@/components/Navbar"; export default function Home() { return ( <AnimatePresence mode="wait"> <Navbar key="navbar" /> </AnimatePresence> ); }
mode="wait":确保退出动画执行完成后再移除组件key="navbar":让AnimatePresence识别组件的挂载/卸载状态
方案2:创建客户端包裹组件(不修改page.js)
如果不想把page.js转为客户端组件,可新建NavbarWrapper.js:
"use client"; import { AnimatePresence } from "framer-motion"; import Navbar from "./Navbar"; export default function NavbarWrapper() { return ( <AnimatePresence mode="wait"> <Navbar key="navbar" /> </AnimatePresence> ); }
然后在page.js中引入这个包裹组件:
import NavbarWrapper from "@/components/NavbarWrapper"; export default function Home() { return ( <> <NavbarWrapper /> </> ); }
2. 确保初始动画在客户端正常执行
如果初始动画仍不生效,可能是服务器渲染的内容与客户端 hydration 存在差异,可通过useAnimation和useEffect手动触发动画:
修改Navbar组件:
"use client"; import { motion, useAnimation } from "framer-motion"; import { useEffect } from "react"; export default function Navbar() { const controls = useAnimation(); useEffect(() => { // 在客户端 hydration 完成后触发动画 controls.start({ opacity: 1, y: 0 }); }, [controls]); return ( <motion.div initial={{ opacity: 0, y: 15 }} animate={controls} exit={{ opacity: 0, y: 15 }} transition={{ delay: 0.25 }} > <div className="w-full h-[112px] bg-primary"></div> </motion.div> ); }
3. 页面切换时的exit动画适配
如果需要在路由切换时触发Navbar的exit动画,需在根布局layout.js中用AnimatePresence包裹页面内容,并监听路由路径作为key:
"use client"; import { AnimatePresence } from "framer-motion"; import { usePathname } from "next/navigation"; export default function RootLayout({ children }) { const pathname = usePathname(); return ( <html lang="en"> <body> <AnimatePresence mode="wait"> {/* 将Navbar放在布局中,用路由路径作为key */} <Navbar key={pathname} /> {children} </AnimatePresence> </body> </html> ); }
内容的提问来源于stack exchange,提问作者kartik kumar
相关产品推荐
相关产品推荐

