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

使用React Router v6 Link时每次导航均显示带最小延迟的加载状态

解决React Router v6中懒加载页面重复导航不显示加载状态的问题

问题原因

React的lazy函数会缓存已加载的组件模块,首次访问时触发pMinDelay的延迟加载逻辑并显示Suspense的fallback,但后续导航时模块已存在于缓存中,不会再触发加载流程,导致加载状态和延迟失效。

解决方案

通过监听路由变化,强制每次导航到目标页面时都显示至少500ms的加载状态,同时保留组件缓存避免重复加载模块。

步骤1:封装延迟加载容器组件

这个组件会监听路由的location.key变化(每次导航都会生成新的key),触发加载状态并维持至少500ms:

import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';

// 自定义Loading组件
const LoadingSpinner = () => (
  <div style={{ padding: '2rem', textAlign: 'center' }}>
    <span>加载中...</span>
  </div>
);

const DelayedPageWrapper = ({ children }: { children: React.ReactNode }) => {
  const [isLoading, setIsLoading] = useState(true);
  const location = useLocation();

  useEffect(() => {
    // 每次路由切换时重置加载状态
    setIsLoading(true);
    const timer = setTimeout(() => {
      setIsLoading(false);
    }, 500);

    // 组件卸载时清除定时器
    return () => clearTimeout(timer);
  }, [location.key]);

  if (isLoading) {
    return <LoadingSpinner />;
  }

  return <>{children}</>;
};

步骤2:保留原有懒加载配置

继续使用lazy和pMinDelay处理首次加载的延迟:

import { lazy } from 'react';
import pMinDelay from 'p-min-delay';

const Page1 = lazy(() => pMinDelay(import('./Page1'), 500));
const Page2 = lazy(() => pMinDelay(import('./Page2'), 500));

步骤3:路由配置整合

将懒加载页面用DelayedPageWrapper包裹,同时保留Suspense处理首次加载的异步逻辑:

import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import { Suspense } from 'react';

function App() {
  return (
    <Router>
      <nav style={{ margin: '1rem 0' }}>
        <Link to="/page1" style={{ marginRight: '1rem' }}>Page1</Link>
        <Link to="/page2">Page2</Link>
      </nav>
      {/* Suspense处理首次加载的异步组件 */}
      <Suspense fallback={<LoadingSpinner />}>
        <Routes>
          <Route
            path="/page1"
            element={
              <DelayedPageWrapper>
                <Page1 />
              </DelayedPageWrapper>
            }
          />
          <Route
            path="/page2"
            element={
              <DelayedPageWrapper>
                <Page2 />
              </DelayedPageWrapper>
            }
          />
        </Routes>
      </Suspense>
    </Router>
  );
}

export default App;

效果说明

  • 首次访问页面:Suspense结合pMinDelay保证至少500ms的加载状态,若组件实际加载时间超过500ms,会持续显示到加载完成。
  • 再次导航页面:DelayedPageWrapper监听路由变化,强制显示500ms加载状态,组件不会重新挂载(状态保留),也不会重复加载模块。
  • 完全符合单页应用要求,无需使用reloadDocument刷新整个应用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:22:07