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

Next.js中useRouter跳转时getStaticProps的Fallback页面不显示问题

Next.js中useRouter跳转时不显示Fallback加载页的原因与解决办法

问题原因

直接输入URL和使用useRouter跳转的核心差异在于页面加载时机与组件挂载逻辑:

  • 直接输入URL时,浏览器会向服务器请求页面,服务器执行getStaticProps后返回页面内容。如果数据未加载完成,返回空props,客户端渲染NewPage时会触发内部的LoadingPage。
  • 使用useRouter跳转时,Next.js会在客户端后台预获取目标页面的组件和getStaticProps结果,这个过程中原页面会持续展示,直到预获取完成才会切换到目标页。此时NewPage的props已经加载完成,自然不会触发内部的LoadingPage。

你的LoadingPage依赖目标页的props是否存在,但跳转过程中目标页组件并未挂载,所以用户看不到加载状态。

解决方案

方案一:全局路由监听显示加载状态

在_app.js中监听路由变化事件,全局显示加载组件,覆盖所有跳转场景:

import { useRouter } from 'next/router';
import { useState, useEffect } from 'react';
import LoadingPage from '../components/LoadingPage';

function MyApp({ Component, pageProps }) {
  const router = useRouter();
  const [isLoading, setIsLoading] = useState(false);

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

    router.events.on('routeChangeStart', startLoading);
    router.events.on('routeChangeComplete', stopLoading);
    router.events.on('routeChangeError', stopLoading);

    return () => {
      router.events.off('routeChangeStart', startLoading);
      router.events.off('routeChangeComplete', stopLoading);
      router.events.off('routeChangeError', stopLoading);
    };
  }, [router]);

  return (
    <>
      {isLoading && <LoadingPage />}
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;

方案二:跳转发起页手动控制加载状态

在触发跳转的页面中,点击按钮后立即显示加载组件,直到跳转完成:

import { useRouter } from 'next/router';
import { useState } from 'react';
import LoadingPage from '../components/LoadingPage';

function OldPage(props) {
  const router = useRouter();
  const [isRedirecting, setIsRedirecting] = useState(false);

  async function redirect(path) {
    setIsRedirecting(true);
    try {
      await router.push({
        pathname: path,
        query: { xyz }
      });
    } finally {
      setIsRedirecting(false);
    }
  }

  return (
    <>
      {isRedirecting && <LoadingPage />}
      <button onClick={() => redirect('/new-page')}>Redirect</button>
    </>
  );
}

方案三:动态路由下启用fallback模式(适用于动态路由页面)

如果NewPage是动态路由(如[id].js),可通过getStaticPaths配置fallback: true,让Next.js先返回加载页,后台生成静态内容后再切换:

// NewPage.js
import { useRouter } from 'next/router';
import LoadingPage from '../components/LoadingPage';

export async function getStaticPaths() {
  return {
    paths: [], // 空数组表示所有路径都动态生成
    fallback: true
  };
}

export async function getStaticProps(context) {
  const data = await someLoadingFunction(context.params.id);
  if (!data) return { notFound: true };
  
  return {
    props: { data },
    revalidate: 60 // 可选,增量静态再生
  };
}

function NewPage(props) {
  const router = useRouter();
  
  // 路由未准备好时显示加载页
  if (!router.isReady) {
    return <LoadingPage />;
  }
  
  if (!props.data) {
    return <div>数据不存在</div>;
  }
  
  return (
    // 页面内容
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:48:22