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
相关产品推荐
相关产品推荐

