React-Router Route Loader初始化加载时执行两次问题求助
问题描述
使用React-Router的route loader特性实现页面加载前数据预取时,遇到初始化页面加载时请求被执行两次的问题。通过Chrome的React Profiler扩展排查发现:App组件仅初始化渲染一次,但RouterProvider组件首次渲染后,会因包含loader数据的“hook 1”变化再次触发渲染,最终导致loader被重复执行。
复现代码如下:
const App = () => { const router = createBrowserRouter([ { path: "/", element: <HomePage />, loader: () => { return fetch(`google.com/services/homepage-tags`); }, }, ]); return <RouterProvider router={router} />; }; export default App;
解决方案
问题根源
每次App组件渲染时都会重新调用createBrowserRouter生成全新的router实例。RouterProvider检测到router实例更新后,会重新初始化整个路由逻辑,自然会再次执行loader函数。
修复方法
方法1:将router实例创建移到组件外部
把router的创建逻辑放在App组件作用域之外,确保只会执行一次:
const router = createBrowserRouter([ { path: "/", element: <HomePage />, loader: () => { return fetch(`google.com/services/homepage-tags`); }, }, ]); const App = () => { return <RouterProvider router={router} />; }; export default App;
方法2:用useMemo缓存router实例
如果router的创建依赖组件内部的状态或props,使用useMemo缓存实例,仅在依赖项变化时重新创建:
import { useMemo } from 'react'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; const App = () => { const router = useMemo(() => createBrowserRouter([ { path: "/", element: <HomePage />, loader: () => { return fetch(`google.com/services/homepage-tags`); }, }, ]), [] // 空依赖数组确保仅初始化时创建一次 ); return <RouterProvider router={router} />; }; export default App;
修改后,router实例只会被创建一次,RouterProvider不会因实例变化重复渲染,loader也就只会执行一次。
内容的提问来源于stack exchange,提问作者Mohammad Ali
相关产品推荐
相关产品推荐

