使用react-hook-form做表单验证提交更新时id为undefined如何解决
问题根源
- 你同时维护了两套表单状态:
react-hook-form托管的表单状态、自己用useState存的ticket状态,二者完全脱节,接口返回的id没有同步到react-hook-form的表单值中,导致提交时data.id为undefined,最终请求URL拼接错误。 - 表单项
TextField同时绑定了react-hook-form的register方法和自定义的value、onChange,二者逻辑冲突,react-hook-form本身就可以托管表单的全量状态,不需要额外用useState重复存储表单字段。
修复步骤
1. 调整类型定义
编辑场景下单据id必然存在,直接把TicketDTO的id改为必填即可:
export interface TicketDTO { id: number, title?: string, description?: string, }
2. 改造react-hook-form初始化
新增reset方法用于接口返回后给表单赋值,补全初始值结构:
const { register, handleSubmit, reset, // 新增reset方法 formState: { errors }, } = useForm<TicketDTO>({ defaultValues: { id: 0, title: "", description: "", }, });
3. 删除冗余的useState状态,同步接口数据到表单
不需要单独用useState存ticket,接口拿到数据后直接调用reset把完整数据赋值给表单,自动携带id:
// 删除冗余的useState定义 // const [ticket, setTicket] = useState<TicketDTO>(); const getSingleTicket = async () => { getTicket(requestParams.id) .then(({ data }) => { // 直接把接口返回的全量数据同步到react-hook-form表单 reset(data); }) .catch((error) => { console.error(error); }); };
4. 改造表单项,删除重复绑定的属性
删掉TextField上自定义的value和onChange,完全交给react-hook-form托管:
<TextField id="title" label="问题名称 *" style={{ margin: 8 }} {...register("title", { required: true, maxLength: 40, })} placeholder="问题名称" helperText={errors.title ? "请输入不超过40字的问题名称" : "请输入问题名称"} fullWidth margin="normal" InputLabelProps={{ shrink: true, }} variant="outlined" error={!!errors.title} // 配合errors展示错误态 />
可选补充
如果业务逻辑中确实需要实时获取当前表单值,直接使用react-hook-form提供的watch方法即可,不需要额外维护状态:
// 监听单个字段 const title = watch('title') // 监听全量表单值 const formAllValues = watch()
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

