Next.js 14页面切换过渡仅刷新生效问题求助
解决Next.js 14 Page Router中Framer Motion页面过渡失效问题
问题现象
使用Next.js 14 Page Router,通过MainLayout统一应用Framer Motion页面淡入淡出过渡效果,仅页面刷新时动画生效,通过Link组件切换页面时无任何过渡效果。已添加'use client'并调整AnimatePresence位置,问题仍未解决。
核心问题分析
- AnimatePresence无法感知页面切换:原代码中页面组件的
key在_app.tsx中定义,但AnimatePresence包裹的motion.div未绑定该key,导致页面切换时AnimatePresence无法识别组件卸载/挂载,无法触发exit动画。 - exit动画配置无效:原exit变体的
opacity设为1,与初始状态无差异,视觉上看不到淡出效果。 - MainLayout未声明为客户端组件:Framer Motion的组件仅能在客户端组件中运行,未添加
'use client'会导致动画逻辑无法在客户端执行。
修复方案及代码调整
1. 修正MainLayout.tsx
添加'use client'声明,绑定页面唯一key,修正exit动画配置:
'use client'; import { AnimatePresence, motion } from 'framer-motion'; import Header from './Header'; import Footer from './Footer'; export default function MainLayout({ children, key, }: { children: React.ReactNode; key: string; }) { const animation = (variants) => ({ initial: 'initial', animate: 'animate', exit: 'exit', variants, }); const pagesVariants = { initial: { opacity: 0, }, animate: { opacity: 1, transition: { duration: 0.6, }, }, exit: { opacity: 0, transition: { duration: 0.6, }, }, }; return ( <> <Header /> <AnimatePresence mode="wait"> <motion.div id="main" className="flex grow flex-col" {...animation(pagesVariants)} key={key} > {children} </motion.div> </AnimatePresence> <Footer /> </> ); }
2. 修正_app.tsx
将router.route作为唯一key传递给MainLayout:
import type { AppProps } from 'next/app'; import MainLayout from '../components/MainLayout'; // 导入字体及样式资源... export default function App({ Component, pageProps, router }: AppProps) { return ( <div id="app" className={`${amarante.variable} ${metal.variable} ${viaodaLibre.variable} ${philosopher.variable} ${styles.app} font-text`} > <MainLayout key={router.route}> <Component {...pageProps} /> </MainLayout> </div> ); }
关键修复点说明
- 客户端组件声明:
'use client'确保Framer Motion的动画逻辑在客户端执行,避免服务端渲染导致的动画失效。 - 唯一key绑定:通过
router.route作为页面唯一标识,每次切换页面时key变化,AnimatePresence会触发旧页面的exit动画和新页面的animate动画。 - 有效exit动画:将exit变体的
opacity设为0,实现页面淡出效果,配合mode="wait"确保前一页动画完成后再加载新页面。
内容的提问来源于stack exchange,提问作者ImEmo
相关产品推荐
相关产品推荐

