React Router v7加载数据过慢时如何显示LoadingIndicator组件?
解决方案
方案1:全局加载提示(最简单)
直接给RouterProvider添加fallback属性,当任何loader处于加载状态时,会显示你指定的加载组件:
- 先创建你的
LoadingIndicator组件(示例):
// components/LoadingIndicator.jsx function LoadingIndicator() { return <div style={{ textAlign: 'center', padding: '2rem' }}>加载中...</div>; } export default LoadingIndicator;
- 修改
main.jsx,导入并配置fallback:
import React from "react"; import ReactDOM from "react-dom/client"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; import Posts, { loader as postsLoader } from "./routes/Posts"; import NewPost, { action as newPostAction } from "./routes/NewPost"; import RootLayout from "./routes/RootLayout"; import LoadingIndicator from "./components/LoadingIndicator"; // 加载组件 import "./index.css"; const router = createBrowserRouter([ { path: "/", element: <RootLayout />, children: [ { path: "/", element: <Posts />, loader: postsLoader, children: [ { path: "create-post", element: <NewPost />, action: newPostAction }, ], }, ], }, ]); const rootElement = document.getElementById("root"); ReactDOM.createRoot(rootElement).render( <React.StrictMode> {/* 添加fallback属性 */} <RouterProvider router={router} fallback={<LoadingIndicator />} /> </React.StrictMode> );
这个方案会在loader加载期间,将页面内容替换为加载组件,适合简单场景。
方案2:局部加载提示(保留RootLayout)
如果希望加载时仍显示RootLayout(比如顶部导航栏),可以调整路由结构并使用useNavigation钩子判断加载状态:
- 调整路由配置,将子路由改为
index路由,让父路由RootLayout优先渲染:
// main.jsx中的router配置 const router = createBrowserRouter([ { path: "/", element: <RootLayout />, children: [ { index: true, // 替代path: "/" element: <Posts />, loader: postsLoader, children: [ { path: "create-post", element: <NewPost />, action: newPostAction }, ], }, ], }, ]);
- 在
RootLayout中判断加载状态,保留导航栏的同时显示加载提示:
// routes/RootLayout.jsx import { Outlet, useNavigation } from "react-router-dom"; import MainHeader from "../components/MainHeader"; import LoadingIndicator from "../components/LoadingIndicator"; function RootLayout() { const navigation = useNavigation(); const isLoading = navigation.state === "loading"; return ( <> <MainHeader /> {/* 加载时显示LoadingIndicator,否则渲染子路由内容 */} {isLoading ? <LoadingIndicator /> : <Outlet />} </> ); } export default RootLayout;
也可以仅给帖子列表区域添加加载提示:
// routes/Posts.jsx import PostsList from "../components/PostsList"; import { Outlet, useNavigation } from "react-router-dom"; import LoadingIndicator from "../components/LoadingIndicator"; function Posts() { const navigation = useNavigation(); const isLoading = navigation.state === "loading"; return ( <> <Outlet /> <main> {isLoading ? <LoadingIndicator /> : <PostsList />} </main> </> ); } export default Posts;
原理说明
RouterProvider的fallback基于React Suspense实现,在路由loader/action执行期间显示备用内容。useNavigation钩子可获取当前路由的导航状态,navigation.state === "loading"表示正在执行loader或action。- 使用
index路由能让父路由组件优先渲染,避免整个页面空白。
内容的提问来源于stack exchange,提问作者KorhanE
相关产品推荐
相关产品推荐

