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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 18:45:24