React Hook Form封装高阶组件动态表单提交无法提取输入数据问题
问题原因
你提交时只能拿到空数据的核心原因是项目中存在两个完全隔离的react-hook-form实例:
- 父组件
member-registration-form.tsx中调用useForm创建了第一个实例,提交事件绑定的是这个实例 - HOC内部又调用
useForm创建了第二个完全独立的实例,所有动态输入框都绑定在这个实例上
两个实例的状态互不连通,父组件自然拿不到子组件内的输入值。同时HOC内部嵌套了<form>标签,不符合HTML表单嵌套规范,也会导致提交行为异常。
修复步骤
1. 改造父组件,统一管理表单实例
将表单默认值移到父组件的useForm中配置,同时把control和register透传给OrderList组件:
import OrderList from "../components/orderList"; import { useForm, SubmitHandler } from "react-hook-form"; import React from "react"; const MemberRegistration = () => { const { register, handleSubmit, control } = useForm({ defaultValues: { test: [{ firstName: "Bill", lastName: "Luo" }] } }); return ( <form onSubmit={handleSubmit(data => console.log(data))}> <OrderList control={control} register={register} /> <input type="submit" /> </form> ); }; export default MemberRegistration;
2. 改造HOC,移除内部独立表单实例
删除HOC内部的useForm调用,改用父组件透传的实例方法,同时删掉嵌套的<form>标签:
import { useFieldArray } from "react-hook-form"; const hoc = (WrappedComponent) => { return (props) => { const { control, register } = props; const { fields, append, prepend, remove } = useFieldArray({ control, name: "test" }); return ( <div> <ul> {fields.map((item, index) => ( <WrappedComponent key={item.id} item={item} removeindex={remove} index={index} register={register} /> ))} </ul> <section> <button type="button" onClick={() => { append({ firstName: "appendBill", lastName: "appendLuo" }); }} > append </button> </section> </div> ); }; }; export default hoc;
可选优化:多层嵌套场景用FormProvider
如果你的表单嵌套层级很深,逐层透传props比较麻烦,可以用react-hook-form提供的FormProvider做全局状态共享:
- 父组件用
FormProvider包裹子组件,传入所有useForm返回的方法 - 子组件通过
useFormContext()直接获取全局表单实例,不需要逐层传props
内容的提问来源于stack exchange,提问作者Kasun Wickramanayake
相关产品推荐
相关产品推荐

