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
相关产品推荐
相关产品推荐

