首页Loader重定向时出现无限循环问题求助
路由Loader触发无限循环的原因及修复方案
我希望提前预取部分数据,编写了如下路由与Loader逻辑,但出现了无限循环问题,恳请告知问题原因及修复方案。
问题代码
homeLoader函数
homeLoader: async (queryClient) => { queryClient.ensureQueryData(['someKey'], doSomething); return redirect(`workspaces/1`); // 此处触发无限循环 }
路由配置
createBrowserRouter( createRoutesFromElements( <Route path='/' element={<Home />} loader={() => homeLoader(queryClient)} // 已注入React Query > <Route path='workspaces' element={<Workspaces />}> <Route path=':workspaceId' element={<Workspace />} /> </Route> </Route> ) ) <RouterProvider router={router} />
依赖版本
"react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.14.2"
问题原因
- 根路由
/的loader执行时,调用redirect('workspaces/1')触发路由导航到/workspaces/1 - 由于
/workspaces/1是根路由/的子路由,React Router加载子路由前会强制执行所有父路由的loader - 这就导致每次导航到
/workspaces/1时,都会重复执行根路由的loader,loader再次触发redirect,形成无限循环
修复方案
方案1:将预取逻辑移到目标子路由
如果预取的数据是/workspaces/1所需,直接在该子路由的loader中执行预取,同时移除根路由的redirect逻辑:
// 修改子路由配置 <Route path='workspaces' element={<Workspaces />}> <Route path=':workspaceId' element={<Workspace />} loader={() => workspaceLoader(queryClient)} /> </Route> // 子路由对应的loader const workspaceLoader = async (queryClient) => { await queryClient.ensureQueryData(['someKey'], doSomething); // 返回子路由业务所需数据,无数据则返回null return null; };
方案2:在根路由loader中添加路径判断
通过loader参数获取当前请求路径,仅当不在目标路由时才执行redirect:
// 修改homeLoader,接收request参数 homeLoader: async ({ request }, queryClient) => { await queryClient.ensureQueryData(['someKey'], doSomething); const currentPath = new URL(request.url).pathname; // 补全绝对路径,避免相对路径导航异常 const targetPath = '/workspaces/1'; if (currentPath !== targetPath) { return redirect(targetPath); } return null; } // 路由loader调用时传递参数 loader={({ request }) => homeLoader({ request }, queryClient)}
方案3:应用初始化时预取数据
在应用入口组件中通过useEffect执行预取,根路由仅负责重定向:
// App组件示例 function App() { const queryClient = useQueryClient(); useEffect(() => { // 使用prefetchQuery而非ensureQueryData,避免阻塞渲染 queryClient.prefetchQuery(['someKey'], doSomething); }, [queryClient]); return <RouterProvider router={router} />; } // 根路由loader简化为 homeLoader: () => redirect('/workspaces/1');
内容的提问来源于stack exchange,提问作者Игор Ташевски
相关产品推荐
相关产品推荐

