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

React Router Loader重复调用问题求助:API请求执行两次

解决React Router Loader重复执行导致API两次请求的问题

问题根源

你的Loader函数被执行了两次,导致控制台两次输出“loading data”,最常见的原因是React 18开发环境下的Strict Mode行为,或者请求没有做缓存处理。

具体原因分析:

  • Strict Mode双重执行:React 18在开发模式下,Strict Mode会重复调用路由loader、组件挂载相关函数,用来检测代码中的副作用问题。如果你的项目入口文件(比如index.js)用<React.StrictMode>包裹了App,就会触发这个现象。
  • 请求无缓存:每次Loader运行时都会新建fetchRequest请求,没有对请求结果做缓存,导致多次执行loader就会发起多次API调用。

解决办法

办法1:临时关闭Strict Mode(开发环境验证用)

如果是Strict Mode导致的,你可以先关闭它来确认问题:
找到项目入口文件(一般是index.js),去掉<React.StrictMode>的包裹:

// 修改前
ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// 修改后
ReactDOM.createRoot(document.getElementById('root')).render(
  <App />
);

注:Strict Mode是React帮你排查代码问题的工具,生产环境不会有双重执行的情况,所以这个方法仅用于开发环境验证,不建议长期关闭。

办法2:给请求加缓存(推荐)

不管是不是Strict Mode的问题,给请求加缓存都是更稳妥的做法,能彻底避免重复请求。修改你的Loader函数:

import React from 'react';
import { useNavigate, useLoaderData, defer, Await } from 'react-router-dom';

// 用全局变量缓存请求的Promise
let cachedDataPromise = null;

export const Loader = () => {
  // 只有缓存不存在时才发起请求
  if (!cachedDataPromise) {
    cachedDataPromise = fetchRequest('', 'GET');
    console.log("loading data");
  }
  return defer({ loaderPromise: cachedDataPromise });
};

// 下面的Home组件代码保持不变
export default function Home() {
  const loaderData = useLoaderData();
  const navigate = useNavigate();
  
  return (
    // ... 你的JSX代码
  );
}

这个方案里,第一次调用Loader时会创建请求并缓存Promise,后续再执行Loader会直接复用缓存的Promise,不会重复发起API请求。页面刷新时全局变量会重置,也能正常发起新请求,完全符合需求。

办法3:React Router内置缓存(进阶)

React Router v6.4+支持loader数据缓存,你可以通过配置router的future选项开启相关特性,不过对于你的场景,办法2已经足够简洁有效。

验证修改

改完之后重新启动项目,控制台应该只会打印一次“loading data”,API也只会被调用一次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:24:52