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

使用react-hook-form做表单验证提交更新时id为undefined如何解决

问题根源

  1. 你同时维护了两套表单状态:react-hook-form 托管的表单状态、自己用useState存的ticket状态,二者完全脱节,接口返回的id没有同步到react-hook-form的表单值中,导致提交时data.id为undefined,最终请求URL拼接错误。
  2. 表单项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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 05:30:04