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

React Hook Form中如何为输入控件传入对象类型值?

通过React Hook Form实现选择控件绑定对象类型字段

你遇到的问题是原生输入控件(select/radio)仅支持字符串、数字类型的值,无法直接绑定对象,下面是两种可行的实现方案:

方案一:通过ID关联(推荐)

这种方式通过存储对象的唯一ID来关联,提交时再从数据源中映射回完整对象,是更稳妥的实现方式。

Select版本代码

interface IDelivery {
  id: number;
  name: string;
}

// 表单字段改为存储配送ID
type FormFields = {
  deliveryId: number;
};

const deliveries: IDelivery[] = [
  { id: 1, name: "QuickDelivery" },
  { id: 2, name: "UPS" },
];

function App() {
  const { register, handleSubmit } = useForm<FormFields>();
  
  const onSubmit = (data: FormFields) => {
    // 通过ID匹配到对应的配送对象
    const selectedDelivery = deliveries.find(d => d.id === data.deliveryId);
    console.log("选中的配送对象:", selectedDelivery);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <select 
        {...register("deliveryId", { 
          valueAsNumber: true // 将控件返回的字符串ID转为数字
        })}
      >
        {deliveries.map(d => (
          <option key={d.id} value={d.id}>
            {d.name}
          </option>
        ))}
      </select>
      <button type="submit">Submit</button>
    </form>
  );
}

export default App;

Radio版本代码

interface IDelivery {
  id: number;
  name: string;
}

type FormFields = {
  deliveryId: number;
};

const deliveries: IDelivery[] = [
  { id: 1, name: "QuickDelivery" },
  { id: 2, name: "UPS" },
];

function App() {
  const { register, handleSubmit } = useForm<FormFields>();
  
  const onSubmit = (data: FormFields) => {
    const selectedDelivery = deliveries.find(d => d.id === data.deliveryId);
    console.log("选中的配送对象:", selectedDelivery);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {deliveries.map(d => (
        <div key={d.id}>
          <input
            type="radio"
            id={`delivery-${d.id}`}
            value={d.id}
            {...register("deliveryId", { valueAsNumber: true })}
          />
          <label htmlFor={`delivery-${d.id}`}>{d.name}</label>
        </div>
      ))}
      <button type="submit">Submit</button>
    </form>
  );
}

export default App;

方案二:JSON序列化与反序列化

通过将对象序列化为字符串作为控件值,提交时再反序列化为对象,适合结构简单的对象。

Select版本代码

interface IDelivery {
  id: number;
  name: string;
}

type FormFields = {
  delivery: IDelivery;
};

const deliveries: IDelivery[] = [
  { id: 1, name: "QuickDelivery" },
  { id: 2, name: "UPS" },
];

function App() {
  const { register, handleSubmit } = useForm<FormFields>();
  
  const onSubmit = (data: FormFields) => {
    console.log("选中的配送对象:", data.delivery);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <select 
        {...register("delivery", {
          setValueAs: (val) => {
            // 增加异常处理,避免解析失败
            try {
              return JSON.parse(val);
            } catch (err) {
              return null;
            }
          }
        })}
      >
        {deliveries.map(d => (
          <option key={d.id} value={JSON.stringify(d)}>
            {d.name}
          </option>
        ))}
      </select>
      <button type="submit">Submit</button>
    </form>
  );
}

export default App;

Radio版本代码

interface IDelivery {
  id: number;
  name: string;
}

type FormFields = {
  delivery: IDelivery;
};

const deliveries: IDelivery[] = [
  { id: 1, name: "QuickDelivery" },
  { id: 2, name: "UPS" },
];

function App() {
  const { register, handleSubmit } = useForm<FormFields>();
  
  const onSubmit = (data: FormFields) => {
    console.log("选中的配送对象:", data.delivery);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {deliveries.map(d => {
        const deliveryStr = JSON.stringify(d);
        return (
          <div key={d.id}>
            <input
              type="radio"
              id={`delivery-${d.id}`}
              value={deliveryStr}
              {...register("delivery", {
                setValueAs: (val) => {
                  try {
                    return JSON.parse(val);
                  } catch (err) {
                    return null;
                  }
                }
              })}
            />
            <label htmlFor={`delivery-${d.id}`}>{d.name}</label>
          </div>
        );
      })}
      <button type="submit">Submit</button>
    </form>
  );
}

export default App;

方案对比

  • 方案一:数据传输更轻量,无序列化风险,适合复杂对象或需要和后端交互的场景,唯一缺点是需要额外映射步骤。
  • 方案二:提交后直接拿到完整对象,无需额外处理,但如果对象包含不可序列化内容(如函数、Symbol)会报错,仅适合简单对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:44:52