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

添加Zod refine方法后表单onSubmit无法触发问题排查

问题描述

我编写了如下Zod表单校验schema:

const createTaskFormSchema = z
  .object({
    duration: z
      .custom<number>()
      .refine((value) => value ?? false, "Required")
      .refine((value) => Number.isFinite(Number(value)), "Invalid number")
      .transform((value) => Number(value)),
    checkpoints: z
      .custom<number>()
      .refine((value) => value ?? false, "Required")
      .refine((value) => Number.isFinite(Number(value)), "Invalid number")
      .transform((value) => Number(value)),
  })
  .refine((data) => data.duration < data.checkpoints, {
    message: "Checkpoints cannot be more than double the duration time",
    path: ["confirm"],
  });

搭配React Hook Form使用:

const form = useForm<z.infer<typeof createTaskFormSchema>>({
  resolver: zodResolver(createTaskFormSchema),
  defaultValues: {
    duration: 0,
    checkpoints: 0,
  },
});

测试代码如下:

function onSubmit(values: z.infer<typeof createTaskFormSchema>) {
  console.log('in here');
  try {
    const result = createTaskFormSchema.parse({            
      duration: 6,
      checkpoints: 3,            
    });
  } catch (err) {
    if (err instanceof z.ZodError) {
      console.log(err.issues);
    }
  }
}

但onSubmit函数完全没有触发(控制台未打印'in here'),移除对象级refine方法后就能正常进入onSubmit,请问哪里出错了?

问题原因
  1. 校验逻辑与提示信息矛盾:你设置的refine条件是data.duration < data.checkpoints(即任务时长必须小于检查点数量才通过校验),但提示信息却是“Checkpoints cannot be more than double the duration time”(检查点数量不能超过任务时长的两倍),逻辑完全相反。比如测试用例里duration=6、checkpoints=3,6不小于3,直接触发校验失败。
  2. 错误路径指向不存在的字段:refine配置里的path: ["confirm"],但你的表单schema中根本没有confirm这个字段。React Hook Form会因为这个不存在的字段校验失败,直接拦截表单提交,导致onSubmit无法执行。
修复方案

步骤1:修正校验逻辑

根据提示信息,正确的校验条件应该是检查点数量不超过任务时长的两倍,调整refine条件:

.refine((data) => data.checkpoints <= data.duration * 2, {
  message: "Checkpoints cannot be more than double the duration time",
  // 步骤2:指定正确的错误关联字段
  path: ["checkpoints"],
})

步骤2:修正错误路径

把path设置为表单中存在的字段(比如checkpoints),这样错误信息会关联到对应的输入框,同时避免因不存在的字段拦截提交。

完整修复后的schema

const createTaskFormSchema = z
  .object({
    duration: z
      .custom<number>()
      .refine((value) => value ?? false, "Required")
      .refine((value) => Number.isFinite(Number(value)), "Invalid number")
      .transform((value) => Number(value)),
    checkpoints: z
      .custom<number>()
      .refine((value) => value ?? false, "Required")
      .refine((value) => Number.isFinite(Number(value)), "Invalid number")
      .transform((value) => Number(value)),
  })
  .refine((data) => data.checkpoints <= data.duration * 2, {
    message: "Checkpoints cannot be more than double the duration time",
    path: ["checkpoints"],
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:16:06