React Router Data Router 数据加载模式

React Router 的 Data Router 模式:用 loader 在路由级加载数据、用 action 处理 mutation、mutation 后自动重新验证 loader。

#type / concept #status / growing #tech / dev / frontend #resource / react

[!info] related notes

React Router Data Router 数据加载模式

一句话定义

React Router 的 Data Router 让路由自己负责加载数据(loader)和处理变更(action),mutation 完成后自动重新验证 loader,保持 UI 和数据同步。

核心机制

loader — 路由级数据加载

export async function consultationLoader({ params }) {
  const conversationId = params.id;

  const conversations = await consultationApi.listConversations({ limit: 50 });

  if (!conversationId || conversationId === 'new') {
    return {
      conversations,
      conversation: null,
      messages: [],
      consultation: null,
    };
  }

  const conversation = await consultationApi.getConversation(conversationId);
  const consultation = await consultationApi.getConsultation(conversationId)
    .catch(() => null);

  return { conversations, conversation, consultation };
}

组件中:

const { conversations, conversation, consultation } =
  useLoaderData<typeof consultationLoader>();

action — 路由级 mutation

export async function consultationAction({ request }) {
  const formData = await request.formData();
  const intent = formData.get('intent');

  if (intent === 'deleteAll') {
    await deleteAllConversations();
    return redirect('/consultation');
  }

  return null;
}

action 完成后,页面上的 loader data 会自动重新验证。

自动重新验证

用户提交删除 → action 执行 → redirect('/consultation')
→ loader 自动重跑 → 页面得到空数据 → 自然显示空状态

不需要手动清空任何 state。

最小例子

// 路由定义
createBrowserRouter([
  {
    path: '/consultation/:id',
    element: <ConsultationPage />,
    loader: consultationLoader,
    action: consultationAction,
  },
]);

// 组件
function ConsultationPage() {
  const data = useLoaderData();
  return <div>{data.conversation?.title}</div>;
}

与 TanStack Query 的对比

维度React Router Loader/ActionTanStack Query
数据加载路由进入时自动触发组件挂载时自动触发
缓存路由级,切换路由可能重新加载queryKey 级,跨路由共享
mutationaction + 自动重新验证useMutation + 手动 invalidate
局部刷新整个路由的 loader 重跑只刷新指定 queryKey
乐观更新需要额外处理内置 onMutate/onError/onSettled
streaming不直接支持通过 setQueryData 增量更新

适用场景

React Router Loader 更适合

  • 进入页面前加载完整数据
  • 提交表单后整体重新验证
  • 页面数据强依赖路由
  • 简单的 CRUD 页面

TanStack Query 更适合

  • 复杂的局部数据变化
  • SSE 流式更新
  • 跨路由缓存复用
  • 乐观更新
  • 需要精细控制 staleTime / refetch

边界与易混淆点

  • Loader 在路由进入时执行,不是在组件渲染时。这意味着数据在组件挂载前就已经准备好了
  • action 完成后的重新验证是自动的,但只重新验证当前路由及父路由的 loader
  • Data Router 不是”不用 TanStack Query”的理由,两者可以共存:路由 loader 加载初始数据,TanStack Query 管理后续的缓存和更新
创建于 2026/7/2 更新于 2026/7/15