如何将父路由loader获取的区域数据传递给子路由loader?
嵌套路由间共享父loader数据的实现方案
针对你提到的嵌套路由场景(父路由/us/new-york获取区域数据,子路由/us/new-york/books/15需要复用该数据并获取书籍数据),以下几种方案可以实现需求:
1. 利用React Router的Loader Context传递数据
React Router v6+的loader函数支持通过context参数在父子路由loader间传递数据,父路由loader把数据挂载到context后,子路由loader可直接读取:
// 父路由loader export async function regionLoader({ request, context }) { const regionRes = await fetch(`/api/regions/us/new-york`); const regionData = await regionRes.json(); // 将区域数据存入context context.regionData = regionData; return regionData; } // 子路由loader export async function bookLoader({ request, params, context }) { // 直接从context获取父路由传递的区域数据 const regionData = context.regionData; // 结合区域数据获取对应书籍 const bookRes = await fetch(`/api/regions/${regionData.id}/books/${params.bookId}`); const bookData = await bookRes.json(); return { regionData, bookData }; }
2. 通过父组件的Outlet传递数据
如果子路由的组件需要使用父路由数据,可在父路由组件中通过Outlet的context属性传递,子组件用useOutletContext读取:
// 父路由组件 import { Outlet, useLoaderData } from "react-router-dom"; export function RegionLayout() { const regionData = useLoaderData(); // 获取父loader返回的区域数据 // 通过Outlet的context传递给子路由组件 return <Outlet context={regionData} />; } // 子路由组件 import { useOutletContext, useLoaderData } from "react-router-dom"; export function BookDetail() { const regionData = useOutletContext(); // 读取父组件传递的区域数据 const bookData = useLoaderData(); // 获取子loader返回的书籍数据 return ( <div> <h3>{regionData.city}地区书籍详情</h3> <p>书名:{bookData.title}</p> </div> ); }
3. 全局状态管理(React Context)
将父路由获取的区域数据存入全局Context,所有子路由的组件或loader都可以访问:
// 定义Region Context import { createContext, useContext } from "react"; const RegionContext = createContext(null); export function RegionProvider({ value, children }) { return ( <RegionContext.Provider value={value}> {children} </RegionContext.Provider> ); } export function useRegionData() { return useContext(RegionContext); }
// 父路由组件 import { Outlet, useLoaderData } from "react-router-dom"; import { RegionProvider } from "./RegionContext"; export function RegionLayout() { const regionData = useLoaderData(); return ( <RegionProvider value={regionData}> <Outlet /> </RegionProvider> ); }
// 子路由组件 import { useLoaderData } from "react-router-dom"; import { useRegionData } from "./RegionContext"; export function BookDetail() { const regionData = useRegionData(); const bookData = useLoaderData(); // 渲染逻辑 }
4. 缓存请求避免重复获取
如果父路由的区域数据请求可以缓存,子路由直接调用相同的请求函数,利用缓存返回数据,无需手动传递:
// 封装带缓存的区域数据请求函数 const regionCache = new Map(); async function getRegionData(path) { if (regionCache.has(path)) { return regionCache.get(path); } const res = await fetch(`/api/regions/${path}`); const data = await res.json(); regionCache.set(path, data); return data; } // 父路由loader export async function regionLoader({ params }) { return getRegionData(`${params.country}/${params.city}`); } // 子路由loader export async function bookLoader({ params }) { // 调用缓存函数,直接获取已有的区域数据 const regionData = await getRegionData(`${params.country}/${params.city}`); const bookData = await fetch(`/api/books/${params.bookId}?regionId=${regionData.id}`).then(res => res.json()); return { regionData, bookData }; }
内容的提问来源于stack exchange,提问作者Boffin
相关产品推荐
相关产品推荐

