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
相关产品推荐
相关产品推荐

