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

Next.js 14 App Router Framer Motion退出动画异常及渲染问题求助

Next.js 14 App Router + Framer Motion 页面过渡动画问题解决

问题背景

在Next.js 14(App Router)中使用Framer Motion实现页面过渡时,仅进入动画生效,退出动画无效果。参考方案实现退出动画后,控制台出现「Warning: Detected multiple renderers concurrently rendering the same context provider」警告,且刷新后前几次页面切换会出现空白,后续才恢复正常。

问题原因

采用的HOC方案通过冻结LayoutRouterContext实现退出动画,但Next.js内部不允许同时渲染多个相同的上下文提供者,这会导致上下文冲突,引发渲染警告和页面空白问题。

解决方案

放弃自定义HOC的方式,直接利用Next.js App Router的template组件结合Framer Motion的AnimatePresence实现页面过渡,无需手动操作路由上下文,从根源避免冲突。

修改后的代码示例

1. 更新 app/layout.tsx

移除自定义的PageAnimatePresence组件,简化布局结构:

import Parallax from './components/Parallax';
import Preloader from './components/Preloader';
import { Theme } from '@radix-ui/themes';

...

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={roboto.variable}>
        <Theme
            hasBackground={false}
            panelBackground='translucent'
        >
          <Parallax>
            {children} {/* 直接渲染children,过渡逻辑交给template处理 */}
          </Parallax>
          <Preloader />
        </Theme>
      </body>
    </html>
  );
}

2. 重构 app/template.tsx

将过渡逻辑整合到template组件中,利用usePathname触发动画:

'use client';

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

interface Props {
    children: ReactNode;
}

const variants = {
  hidden: { opacity: 0, x: "100%", y: 0 },
  enter: { opacity: 1, x: 0, y: 0 },
  exit: { opacity: 0, x: "-100%", y: 0 }
};

export default function Template({ children }: Props) {
  const pathname = usePathname();

  return (
    <AnimatePresence mode="wait">
      <motion.main
        key={pathname}
        variants={variants}
        initial="hidden"
        exit="exit"
        animate="enter"
        transition={{ type: 'linear', duration: 0.2 }}
      >
        {children}
      </motion.main>
    </AnimatePresence>
  );
}

3. 删除冗余组件

移除app/components/HOC/FrozenRoute.tsx和app/components/HOC/PageAnimatePresence.tsx两个自定义组件,清理代码。

方案说明

  • template组件特性:App Router的template是页面的共享容器,页面切换时旧页面的template会执行exit动画,新页面的template执行enter动画,无需额外处理上下文。
  • AnimatePresence触发逻辑:通过usePathname作为motion.main的key,路径变化时AnimatePresence能准确识别组件替换,触发完整的进出动画流程。
  • 避免上下文冲突:完全移除对LayoutRouterContext的手动操作,符合Next.js内部渲染机制,消除警告和空白问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 05:24:53