使用React Router defer时,如何让React.Suspense全程显示加载器?
解决React Router defer + Suspense加载器显示过短的问题
你当前代码的核心问题在于:loader函数中使用了await fetch,这会让路由完全等待API请求完成后才渲染页面组件。此时传给defer的data.json()是一个已经接近完成的Promise,导致Suspense的fallback只能短暂显示,无法实现从API调用开始就展示加载状态的需求。
解决方案
去掉fetch前的await,直接将包含API请求和解析逻辑的Promise传给defer,让loader立即返回结果。这样组件渲染时,Suspense会捕获到未完成的Promise,持续显示加载器直到数据就绪。
修改后的main.jsx代码:
import React, { useRef } from "react"; import ReactDOM from "react-dom/client"; import { createBrowserRouter, defer, RouterProvider } from "react-router-dom"; import Homepage from "./App"; import "./index.css"; const router = createBrowserRouter([ { path: "/", element: <Homepage />, loader: () => { // 直接返回包含fetch和解析的Promise链,不等待完成 const resultsPromise = fetch('https://api.rapidmock.com/mocks/j4CMM', { headers : { "x-rapidmock-delay": 2500 } }).then(res => res.json()); return defer({ results: resultsPromise, }); }, }, ]); ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> );
另一种等价写法(用async IIFE)
如果习惯用async/await语法,也可以用立即执行的async函数返回Promise:
loader: () => { const resultsPromise = (async () => { const res = await fetch('https://api.rapidmock.com/mocks/j4CMM', { headers : { "x-rapidmock-delay": 2500 } }); return res.json(); })(); return defer({ results: resultsPromise }); }
两种写法的效果一致:loader会立即返回defer对象,其中results是未完成的Promise。当Homepage组件渲染时,Suspense会触发fallback加载状态,直到API请求完成后才渲染Await中的内容。
内容的提问来源于stack exchange,提问作者Rishabh Kapoor
相关产品推荐
相关产品推荐

