使用Controller集成React Hook Form自定义输入时验证不生效的解决问询
问题:React Hook Form Controller组件验证不生效,错误对象无法填充
我正在用React Hook Form的useForm钩子搭建自定义输入字段,提交时能正常获取输入值,但验证规则完全不生效,error对象始终为空。相关代码如下:
useForm初始化代码
const { control, handleSubmit, register, formState, setValue, getValues } = useForm({ mode: 'onSubmit', reValidateMode: 'onSubmit', shouldFocusError: true, defaultValues: { myIdFld: '123' }, resolver: yupResolver(schema) }); const onSubmit = (data) => { alert(JSON.stringify(data)); }; const onErrors = (data) => { alert('Errors !'); };
字段配置
let sampleField = {"id":"myIdFld","mandatory":true,"visible":true,"maxLength":5,"items":[],"gridItems":[],"disabled":false,"hidden":false,"readonly":false,"fieldLabel":"My ID 1","pattern":/[A-Za-z]{3}/,"editable":true};
父组件JSX
return ( <> <form onSubmit={handleSubmit((data) => console.log('Save Successful ', data))}> <Field name={sampleField.id} control={control} label={sampleField.fieldLabel} formFieldProps={{ necessity: (sampleField.mandatory === true) ?'required': 'optional' }} field={sampleField} {...props} /> <Button onClick={handleSubmit(onSubmit, onErrors)} type="submit" variant="cta">Submit</Button> </form> </> )
Field组件代码
import { Controller } from "react-hook-form" <Controller control={control} rules={{required: "The field is required"}} name={name} render={({ field: { ref, ...restField }, fieldState: { error } }) => { const validationMessage = error ? error.message : helperText; const validationStatus = error && 'error'; return ( <FormField validationStatus={validationStatus} {...formFieldProps}> <FormFieldLabel {...formFieldLabelProps}> {label} </FormFieldLabel> <Input inputRef={ref} {...restField} {...restProps} /> <FormFieldHelperText>{validationMessage}</FormFieldHelperText> </FormField> ); }} />
尝试过的验证规则生成函数
const createValidationRules = (fieldConfig) => { const rules = {}; if (fieldConfig.mandatory) { rules.required = fieldConfig.customRequiredMessage || "This field is required"; } if (fieldConfig.pattern) { rules.pattern = { value: fieldConfig.pattern, message: fieldConfig.customPatternMessage || "Invalid format" }; } if (fieldConfig.maxLength) { rules.maxLength = { value: fieldConfig.maxLength, message: fieldConfig.customMaxLengthMessage || `Maximum length is ${fieldConfig.maxLength}` }; } return rules; };
解决步骤
1. 移除全局Yup解析器的冲突
你当前的useForm配置同时使用了yupResolver(schema)和Controller的rules属性,两者会互相覆盖导致验证失效。如果要使用自定义规则验证,需要删除全局resolver配置:
const { control, handleSubmit, register, formState, setValue, getValues } = useForm({ mode: 'onSubmit', reValidateMode: 'onSubmit', shouldFocusError: true, defaultValues: { myIdFld: '123' } // 移除此行:resolver: yupResolver(schema) });
2. 正确传递动态验证规则到Controller
createValidationRules函数逻辑没问题,但需要确保生成的规则正确传入Field组件的Controller,替换硬编码的规则:
- 父组件调用Field时传入生成的规则:
<Field name={sampleField.id} control={control} label={sampleField.fieldLabel} formFieldProps={{ necessity: sampleField.mandatory ? 'required' : 'optional' }} field={sampleField} rules={createValidationRules(sampleField)} // 新增此行 {...props} />
- Field组件中使用传入的规则:
<Controller control={control} rules={rules} // 替换为传入的动态规则 name={name} render={({ field: { ref, ...restField }, fieldState: { error } }) => { // 原有渲染逻辑不变 }} />
3. 确保自定义Input组件正确受控
自定义Input必须正确处理value和onChange属性(已通过...restField传入),示例如下:
const Input = ({ inputRef, value, onChange, ...props }) => { return ( <input ref={inputRef} value={value} onChange={(e) => onChange(e.target.value)} {...props} /> ); };
4. 修复重复的提交逻辑绑定
当前form和Button都绑定了handleSubmit,会导致提交逻辑重复。只需在form标签上绑定一次即可:
return ( <> <form onSubmit={handleSubmit(onSubmit, onErrors)}> <Field // 原有属性不变,加上rules参数 rules={createValidationRules(sampleField)} /> <Button type="submit" variant="cta">Submit</Button> </form> </> );
完成以上修改后,提交表单时会触发sampleField配置中的验证规则,error对象会被正确填充,错误信息也会显示在FormFieldHelperText中。
内容的提问来源于stack exchange,提问作者copenndthagen
相关产品推荐
相关产品推荐

