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

Next.js 13路由切换时如何实现加载页面?

Next.js 13 路由切换加载状态不生效问题解决方案

问题根源

你当前的代码把Suspense包裹了Header、页面内容和NavigationBar,但Header和导航栏是布局中固定的静态元素,路由切换时它们不会重新渲染,导致Suspense无法捕获页面内容的加载状态。另外,若页面组件没有异步操作(比如服务器组件的fetch),Suspense也不会触发。

解决方案1:调整Suspense位置

将Suspense仅包裹页面内容{children},让Header和导航栏始终显示,只有页面切换时触发加载:

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <Head>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <body>
        <Script src="https://telegram.org/js/telegram-web-app.js" />
        <Providers>
          <Header />
          {/* 仅对页面内容使用Suspense */}
          <Suspense fallback={<LoadingPage />}>
            {children}
          </Suspense>
          <NavigationBar />
        </Providers>
        <Toaster
          closeButton={false}
          position="bottom-center"
          toastOptions={{
            duration: 3000,
          }}
        />
      </body>
    </html>
  );
}

解决方案2:监听路由切换事件(客户端组件)

如果页面是静态的无异步操作,或者需要更精准的加载状态控制,可通过useRouter监听路由切换事件:

  1. 创建客户端组件LoadingWrapper.tsx:
'use client';

import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';

export default function LoadingWrapper({ children }: { children: React.ReactNode }) {
  const router = useRouter();
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const startLoading = () => setIsLoading(true);
    const endLoading = () => setIsLoading(false);

    // 绑定路由切换事件
    router.events.on('routeChangeStart', startLoading);
    router.events.on('routeChangeComplete', endLoading);
    router.events.on('routeChangeError', endLoading);

    // 组件卸载时解绑事件
    return () => {
      router.events.off('routeChangeStart', startLoading);
      router.events.off('routeChangeComplete', endLoading);
      router.events.off('routeChangeError', endLoading);
    };
  }, [router]);

  return isLoading ? <LoadingPage /> : <>{children}</>;
}
  1. 在RootLayout中使用该Wrapper:
<Providers>
  <Header />
  <LoadingWrapper>
    {children}
  </LoadingWrapper>
  <NavigationBar />
</Providers>

注意事项

  • 若页面是服务器组件,需包含异步操作(如fetch)才能触发Suspense的fallback;
  • useRouter的事件监听仅支持客户端组件,必须添加'use client'指令;
  • 确保LoadingPage组件可以正常在服务器或客户端渲染,避免 hydration 错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:55:29