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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:20:14