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

如何在React Router Actions中使用JSON数据?为何限制FormData?

解决方案与解释

一、在React Router Actions中提交JSON数据

有两种可行方式适配嵌套结构并提交JSON:

1. 手动序列化表单数据为JSON

在提交前将FormValues转为JSON字符串,通过FormData中转,再在action中解析转发:

  • 组件内提交逻辑:
const formValues = { /* 你的表单数据 */ };
fetcher.submit(
  { json: JSON.stringify(formValues) },
  { method: 'post', action: '/transactions/add' }
);
  • 路由action处理:
<Route
  path="/transactions/add"
  element={<AddSong />}
  action={async ({ request }) => {
    const formData = await request.formData();
    const jsonString = formData.get('json');
    return fetch('/api/transactions/add', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
      },
      body: jsonString,
    });
  }}
/>

2. 直接提交JSON对象(React Router v6.4+)

如果使用v6.4及以上版本,可直接传入JSON对象并指定请求头,无需FormData中转:

  • 组件内提交逻辑:
const formValues = { /* 你的表单数据 */ };
fetcher.submit(formValues, {
  method: 'post',
  action: '/transactions/add',
  headers: {
    'Content-Type': 'application/json',
  },
});
  • 路由action处理:
<Route
  path="/transactions/add"
  element={<AddSong />}
  action={async ({ request }) => {
    const jsonData = await request.json();
    return fetch('/api/transactions/add', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(jsonData),
    });
  }}
/>

这种方式完全适配嵌套结构,更贴合后端的JSON处理需求。

二、React Router默认使用FormData的原因

  1. 原生表单兼容性:FormData是浏览器原生支持的格式,和传统HTML表单提交行为一致,即使在JS受限环境下也能保持基础提交能力,同时对齐原生表单的设计逻辑。
  2. 多类型数据支持:FormData可直接处理文件上传等二进制数据,这是JSON无法直接实现的功能,覆盖了更多表单场景。
  3. 通用性与学习成本:键值对结构能适配绝大多数简单表单,React Router的<Form>组件可自动收集字段值组装成FormData,和原生表单行为一致,降低开发者学习成本。
  4. 路由action的设计定位:action主要用于处理通用表单提交场景,而JSON更多偏向API交互,FormData作为默认选择更符合表单提交的通用需求。

需要注意的是,React Router并没有强制限制只能用FormData,开发者可根据实际需求手动设置请求头和请求体,实现JSON格式的提交。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 03:25:27