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

Zod refine校验复选框未触发实时渲染问题求助

React Hook Form 复选框组校验后错误提示无法实时清除

我实现了一个复选框组的约束逻辑,要求用户必须至少选择一个复选框。但遇到了问题:当用户未满足约束就点击提交按钮后,即便后续选中了某个复选框,错误提示仍会持续显示,直到再次点击提交按钮。

现有代码

const schema = object({
  checkboxGroup: object({
    a: boolean(),
    b: boolean(),
  }).refine(
    ({ a, b }) => {
      return a || b;
    },
    {
      message: 'You must select at least one',
    },
  ),
});

export type SchemaType = TypeOf<typeof schema>;

export default function Foo() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<SchemaType>({
    resolver: zodResolver(schema),
  });

  return (
    <Box
      component="form"
      noValidate
      autoComplete="off"
      onSubmit={handleSubmit(() => {})}
    >
      <FormControl
        required
        error={!!errors.checkboxGroup}
        component="fieldset"
        variant="standard"
      >
        <FormLabel component="legend">CheckboxGroup</FormLabel>
        <FormGroup>
          <FormControlLabel
            control={<Checkbox />}
            {...register('checkboxGroup.a')}
            label="A"
          />
          <FormControlLabel
            control={<Checkbox />}
            {...register('checkboxGroup.b')}
            label="B"
          />
        </FormGroup>
        <FormHelperText error={!!errors.checkboxGroup}>
          {errors.checkboxGroup ? errors.checkboxGroup.message : ''}
        </FormHelperText>
      </FormControl>
      <Button variant="contained" type="submit">
        Save
      </Button>
    </Box>
  );
}

问题原因

React Hook Form 默认仅在提交表单或手动触发校验时才会运行 Zod resolver。提交表单触发错误后,后续修改复选框状态不会自动重新校验对应字段,导致错误提示一直留存。

解决方案

有两种常用方法可以实现错误提示的实时更新:

方法1:手动触发特定字段校验

从 useForm 中解构出 trigger 方法,在复选框变化时手动触发 checkboxGroup 字段的校验:

export default function Foo() {
  const {
    register,
    handleSubmit,
    formState: { errors },
    trigger, // 新增:获取trigger方法
  } = useForm<SchemaType>({
    resolver: zodResolver(schema),
  });

  return (
    <Box
      component="form"
      noValidate
      autoComplete="off"
      onSubmit={handleSubmit(() => {})}
    >
      <FormControl
        required
        error={!!errors.checkboxGroup}
        component="fieldset"
        variant="standard"
      >
        <FormLabel component="legend">CheckboxGroup</FormLabel>
        <FormGroup>
          <FormControlLabel
            control={<Checkbox onChange={() => trigger('checkboxGroup')} />} // 新增:变化时触发校验
            {...register('checkboxGroup.a')}
            label="A"
          />
          <FormControlLabel
            control={<Checkbox onChange={() => trigger('checkboxGroup')} />} // 新增:变化时触发校验
            {...register('checkboxGroup.b')}
            label="B"
          />
        </FormGroup>
        <FormHelperText error={!!errors.checkboxGroup}>
          {errors.checkboxGroup ? errors.checkboxGroup.message : ''}
        </FormHelperText>
      </FormControl>
      <Button variant="contained" type="submit">
        Save
      </Button>
    </Box>
  );
}

这种方式只会针对 checkboxGroup 字段触发校验,性能更优,适合只需要实时校验特定字段的场景。

方法2:全局开启实时校验模式

在 useForm 配置中设置 mode: "onChange",让所有字段在值变化时自动触发校验:

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm<SchemaType>({
  resolver: zodResolver(schema),
  mode: "onChange", // 新增:开启实时校验
});

这种方式更省心,适合需要对所有字段做实时校验的表单,但如果表单字段较多,可能会带来轻微的性能开销。

效果验证

修改后,当用户提交表单触发错误,再选中任意复选框时,错误提示会立即消失,无需再次点击提交按钮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:45:58