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

Next.js 13迁移报错:invariant expected app router to be mounted

解决Next.js 13迁移后调用notFound()触发“invariant expected app router to be mounted”错误

问题根源

当页面调用notFound()时,App Router会中断当前路由的渲染流程,但你的根layout.tsx中存在异步数据获取逻辑,且传递给Providers组件的子元素里,有客户端组件提前调用了useRouter()——useRouter()依赖App Router的上下文环境,而notFound()触发时路由上下文尚未完全挂载,因此抛出错误。

具体解决方案

1. 调整根Layout的异步数据获取位置

根Layout是所有路由共享的,不要在根Layout中做异步数据获取并传递给Providers,把数据逻辑移到具体页面的Server Component中:

// 原错误的app/layout.tsx
async function RootLayout({ children }) {
  const data = await fetch('/api/data'); // 根Layout异步获取数据
  return (
    <html>
      <body>
        <Providers data={data}>{children}</Providers>
      </body>
    </html>
  );
}

// 修改后的app/layout.tsx
function RootLayout({ children }) {
  // 移除根Layout的异步数据逻辑
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

// app/(main)/page.tsx(Server Component)
async function Page() {
  const data = await fetch('/api/data');
  if (!data.ok) {
    notFound(); // 仅在页面层触发notFound,此时路由上下文已正常初始化
  }
  return <MainPage data={await data.json()} />;
}

2. 限制useRouter()的执行时机

如果Providers内的客户端组件必须使用useRouter(),通过useEffect延迟逻辑执行,确保路由上下文已挂载:

'use client';
import { useRouter, useEffect } from 'next/navigation';

function ClientComponentInProviders() {
  const router = useRouter();

  useEffect(() => {
    // 仅在组件挂载后、路由上下文就绪时使用router
    const handleRouteChange = () => {
      console.log('路由变化', router.pathname);
    };
    router.events.on('routeChangeComplete', handleRouteChange);
    return () => router.events.off('routeChangeComplete', handleRouteChange);
  }, [router]);

  return <div>客户端组件内容</div>;
}

3. 用更安全的路由hooks替代useRouter()

如果只是获取路由信息(而非跳转),改用usePathname或useSearchParams,这些hooks在App Router中对上下文的依赖更稳定:

'use client';
import { usePathname } from 'next/navigation';

function ClientComponentInProviders() {
  const pathname = usePathname();
  // 直接使用pathname,无需依赖useRouter
  return <div>当前路径:{pathname}</div>;
}

4. 确保notFound()仅在Server Component中调用

notFound()是Server Component专属方法,不要在客户端组件中调用。如果客户端需要触发404,改用router.push('/404')或者自定义404组件。

内容的提问来源于stack exchange,提问作者Milos N.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:23:24