React Router v6:单个loader多fetch实现及useLoaderData数据获取
在React Router v6的createBrowserRouter中实现单个Loader多请求并通过useLoaderData获取数据
完全可以在单个loader中执行多个fetch请求,并且仅通过useLoaderData获取数据,不需要依赖useEffect——这正是React Router v6 loader机制的设计初衷:在组件渲染前预加载所需数据。
你代码的核心问题
你当前的代码中,fetch返回的是Response对象,而非解析后的JSON数据。需要在Promise.all中对每个请求的响应调用.json()(这也是异步操作),才能拿到最终可用的数据。
修正后的Loader代码
export const storeLoader = async ({ params }) => { const [store, departments, items] = await Promise.all([ // 对每个fetch的响应解析JSON fetch(`/stores/${params.id}`).then(res => res.json()), fetch(`/departments/?store=${params.id}`).then(res => res.json()), fetch(`/items/?store=${params.id}`).then(res => res.json()), ]); // 返回整合后的多份数据 return { store, departments, items }; }
如果需要更严谨的错误处理(比如判断请求是否成功),可以在解析前检查响应状态:
export const storeLoader = async ({ params }) => { const [store, departments, items] = await Promise.all([ fetch(`/stores/${params.id}`).then(res => { if (!res.ok) throw new Error('店铺数据获取失败'); return res.json(); }), fetch(`/departments/?store=${params.id}`).then(res => { if (!res.ok) throw new Error('部门数据获取失败'); return res.json(); }), fetch(`/items/?store=${params.id}`).then(res => { if (!res.ok) throw new Error('商品数据获取失败'); return res.json(); }), ]); return { store, departments, items }; }
组件中获取数据
你的组件代码写法是正确的,直接通过useLoaderData解构即可拿到所有数据:
import { useLoaderData } from 'react-router-dom'; const Store = () => { const { store, departments, items } = useLoaderData(); // 直接使用数据渲染UI return ( <div> <h1>{store.name}</h1> <h2>部门列表</h2> <ul>{departments.map(dept => <li key={dept.id}>{dept.name}</li>)}</ul> {/* 商品列表渲染... */} </div> ); }
额外说明
- 这种分请求获取数据的方式,相比MongoDB的
populate更灵活,能避免返回体积过大的JSON,也更适配跨API(如天气、地图数据)的场景。 - loader会在组件渲染前完成数据加载,相比
useEffect在组件挂载后请求,能减少页面加载时的状态闪烁,提升用户体验。
内容的提问来源于stack exchange,提问作者Jeff
相关产品推荐
相关产品推荐

