Material UI+React Hook Form:禁用复选框无法提交问题求助
表单提交时禁用必填复选框导致react-hook-form验证失败的问题解决
我使用Next.js + TypeScript,搭配react-hook-form和Material-UI实现表单提交时禁用所有字段的功能,目前文本框、选择器和单选框都正常生效,但必填复选框出现问题——给<FormControl>添加disabled={isSubmitting}属性后,react-hook-form不再识别复选框的值,直接标记为必填错误。
相关组件代码如下:
const id = "vehicles"; const OPTIONS = ["bike", "car", "truck", "van"]; export const Vehicles = (): JSX.Element => { const { register, formState: { errors } } = useFormContext(); const error = get(errors, id); return ( <CheckboxMultiFieldInput label="Vehicles" error={error} required> {OPTIONS.map(startCase).map((option: string) => ( <CheckBoxOptionMap value={option} label={option} key={option} registerProps={register(id, { required: true })} /> ))} </CheckboxMultiFieldInput> ); }; export const CheckBoxOptionMap = ({ value, label, registerProps }: CheckboxOptionMapInterface) => { // Also can't submit with the disabled prop here instead // const { // formState: { isSubmitting } // } = useFormContext(); return ( <FormControlLabel value={value} control={<Checkbox {...registerProps} />} label={label} aria-label={`${label}-option-${value}`} // disabled={isSubmitting} /> ); }; export const CheckboxMultiFieldInput = ({ children, label, error, required }: CheckboxMultiFieldInterface): JSX.Element | null => { // Cannot submit anymore once this disabled prop is added // const { // formState: { isSubmitting } // } = useFormContext(); if (!children || children.length === 0) { return null; } return ( <div className="inputBox"> <FormControl error={error !== undefined} required={required} // disabled={isSubmitting} > <FormLabel>{label}</FormLabel> {children} {error && ( <FormHelperText id={`${label}-helper-text`}> {error.message || error.type} </FormHelperText> )} </FormControl> </div> ); };
问题根源
Material-UI的<FormControl>添加disabled属性后,会批量禁用内部所有表单控件,但react-hook-form默认不会收集禁用字段的值,导致提交时验证逻辑认为复选框未被勾选,触发必填错误。
解决办法
方案1:单独控制复选框禁用状态并强制RHF收集值
这种方式不需要修改整体结构,只需调整两处代码:
- 更新
Vehicles组件中register的配置,添加disabled: false强制RHF收集字段值:register(id, { required: true, disabled: false }) - 修改
CheckBoxOptionMap组件,获取isSubmitting状态并直接给<Checkbox>添加禁用属性:export const CheckBoxOptionMap = ({ value, label, registerProps }: CheckboxOptionMapInterface) => { const { formState: { isSubmitting } } = useFormContext(); return ( <FormControlLabel value={value} control={<Checkbox {...registerProps} disabled={isSubmitting} />} label={label} aria-label={`${label}-option-${value}`} /> ); }; - 确保
<FormControl>上的disabled属性保持注释或移除,避免批量禁用影响字段收集。
方案2:使用Controller组件接管字段控制
如果需要更灵活的字段控制,推荐用react-hook-form的Controller组件包裹复选框,明确指定即使控件禁用也保留值的收集逻辑:
// 修改Vehicles组件 export const Vehicles = (): JSX.Element => { const { control, formState: { errors, isSubmitting } } = useFormContext(); const error = get(errors, id); return ( <CheckboxMultiFieldInput label="Vehicles" error={error} required> {OPTIONS.map(startCase).map((option: string) => ( <Controller name={id} control={control} rules={{ required: true }} render={({ field }) => ( <FormControlLabel value={option} control={<Checkbox {...field} disabled={isSubmitting} />} label={option} aria-label={`${option}-option-${option}`} /> )} key={option} /> ))} </CheckboxMultiFieldInput> ); };
关键说明
- react-hook-form的
register方法中,disabled选项是控制是否收集字段值的开关,设置为false可以强制收集,不受控件本身disabled属性的影响。 - 避免用
<FormControl>的disabled批量禁用控件,因为这会让RHF默认忽略这些字段的值,导致验证失败。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

