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

Remix:如何在子路由中获取父路由Action的返回数据?

如何在Remix子路由中复用父路由Action已获取的数据

下面提供三种可行方案,根据你的场景选择合适的方式:


方案1:通过父组件Outlet传递上下文

如果子路由是通过父路由的<Outlet>渲染的,可以直接把父路由Action返回的数据通过Outlet的context传递给子路由组件,无需额外请求。

父路由(parent.tsx)代码:

import { Outlet, useActionData } from '@remix-run/react';
import type { ActionFunction } from '@remix-run/node';

export const action: ActionFunction = async ({ request }) => {
  // 模拟获取数据
  const data = await fetch('https://api.example.com/parent-data').then(res => res.json());
  return data;
};

export default function ParentRoute() {
  // 获取Action返回的数据
  const parentActionData = useActionData<typeof action>();
  
  return (
    <div>
      {/* 通过Outlet的context传递数据给子路由 */}
      <Outlet context={{ parentData: parentActionData }} />
    </div>
  );
}

子路由(parent.$id.tsx)代码:

import { useOutletContext } from '@remix-run/react';

// TypeScript可选:定义上下文类型
type ParentContext = {
  parentData: Awaited<ReturnType<typeof import('./parent').action>>;
};

export default function ChildRoute() {
  // 从Outlet上下文获取父路由Action的数据
  const { parentData } = useOutletContext<ParentContext>();

  return (
    <div>
      <h3>子路由展示父数据:</h3>
      <pre>{JSON.stringify(parentData, null, 2)}</pre>
    </div>
  );
}

注意:这种方式仅适用于父路由Action触发后的同页面渲染场景(比如表单提交后页面不跳转,直接渲染子路由)。如果用户刷新子路由页面,父路由的Action不会重新执行,useActionData会返回undefined,此时子路由拿不到数据。


方案2:用Session临时存储数据

如果需要跨请求复用父路由Action的数据(比如用户提交表单后跳转到子路由页面),可以把数据存入Session,子路由从Session中读取。

父路由(parent.tsx)代码:

import { json } from '@remix-run/node';
import type { ActionFunction } from '@remix-run/node';

export const action: ActionFunction = async ({ request, context }) => {
  const data = await fetch('https://api.example.com/parent-data').then(res => res.json());
  
  // 将数据存入Session
  const session = await context.getSession();
  session.set('parentActionData', data);
  
  return json(data, {
    headers: {
      'Set-Cookie': await context.commitSession(session),
    },
  });
};

子路由(parent.$id.tsx)代码:

import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import type { LoaderFunction } from '@remix-run/node';

export const loader: LoaderFunction = async ({ context }) => {
  // 从Session中读取数据
  const session = await context.getSession();
  const parentData = session.get('parentActionData');
  
  // 可选:读取后删除Session中的数据,避免长期存储
  session.unset('parentActionData');
  
  return json({ parentData }, {
    headers: {
      'Set-Cookie': await context.commitSession(session),
    },
  });
};

export default function ChildRoute() {
  const { parentData } = useLoaderData<typeof loader>();

  return (
    <div>
      <h3>子路由从Session获取父数据:</h3>
      <pre>{JSON.stringify(parentData, null, 2)}</pre>
    </div>
  );
}

注意:Session存储在Cookie中,数据大小有限制(一般不超过4KB),不适合存储大型数据。


方案3:提取共享缓存函数复用数据

如果数据是通用的、允许短期缓存,可以把数据获取逻辑抽成带缓存的共享函数,父路由Action和子路由Loader都调用这个函数,避免重复请求。

共享数据函数(utils/fetchParentData.ts):

// 内存缓存,单实例有效;多实例部署建议用Redis等分布式缓存
let cachedData: any = null;
let cacheExpiry: number | null = null;

export async function fetchParentData() {
  const now = Date.now();
  // 如果缓存存在且未过期,直接返回缓存数据
  if (cachedData && cacheExpiry && now < cacheExpiry) {
    return cachedData;
  }

  // 重新获取数据
  const data = await fetch('https://api.example.com/parent-data').then(res => res.json());
  
  // 设置缓存(比如1分钟过期)
  cachedData = data;
  cacheExpiry = now + 60 * 1000;

  return data;
}

父路由(parent.tsx)代码:

import type { ActionFunction } from '@remix-run/node';
import { fetchParentData } from '~/utils/fetchParentData';

export const action: ActionFunction = async () => {
  const data = await fetchParentData();
  return data;
};

子路由(parent.$id.tsx)代码:

import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import type { LoaderFunction } from '@remix-run/node';
import { fetchParentData } from '~/utils/fetchParentData';

export const loader: LoaderFunction = async () => {
  const parentData = await fetchParentData();
  return json({ parentData });
};

export default function ChildRoute() {
  const { parentData } = useLoaderData<typeof loader>();

  return (
    <div>
      <h3>子路由通过缓存函数获取父数据:</h3>
      <pre>{JSON.stringify(parentData, null, 2)}</pre>
    </div>
  );
}

注意:内存缓存仅在单个服务器实例中有效,如果是多实例部署(比如云服务器集群),建议使用Redis等分布式缓存来保证缓存一致性。


内容的提问来源于stack exchange,提问作者arlioli03

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 06:33:20