You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将父路由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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:46:21