React Hook Form:register的disabled生效但maxLength未返回?求原因与解决
问题场景
我在使用React-Hook-Form时,将register传入自定义textarea、input等组件。当传入选项{disabled: true, maxLength: 40}后,控制台查看register对象,发现仅包含disabled属性,没有maxLength。控制台输出如下:
{ "disabled": true, "name": "test", "onBlur" : ..., "onChange" : ..., "ref" : ... , }
我需要使用register选项中设置的maxLength值,查看UseFormRegisterReturn类型时发现它包含maxLength属性,但实际取值时却不存在。尝试passedRegister.maxLength读取始终为undefined,passedRegister.disabled却能正常获取,且register选项中的多数属性都未在返回对象中显示。相关代码示例:
const TestPage = (props: Props) => { const rhf = useForm(); const testRegister = rhf.register('test', { maxLength: 40, disabled: true }); return ( <div className="text-grayscale-130"> <form> <input type="text" {...testRegister} /> <div>{`maxLength : ${testRegister.maxLength}`}</div> </form> </div> ); };
问题解答
1. 为什么会出现这种情况?
React-Hook-Form的register函数返回对象,仅包含直接作用于表单元素的原生DOM属性和表单控制核心方法(如onChange、onBlur、ref)。disabled是input/textarea支持的原生DOM状态属性,会被直接注入返回对象;而maxLength属于验证规则类配置,register仅会在内部用它做表单校验逻辑,不会将其暴露在返回的属性集合中。
2. 若无法读取maxLength,为何该属性包含在UseFormRegisterReturn类型中?
这是TypeScript类型定义的设计考量:UseFormRegisterReturn类型覆盖了所有原生表单元素可能支持的DOM属性(包括maxLength、minLength、pattern等),目的是适配所有可能的DOM属性传入场景。但实际上只有disabled、readOnly这类直接控制元素状态的属性会被添加到返回对象,验证规则类属性不会被挂载,导致类型定义和运行时实际对象存在差异。
3. 如何获取在register选项中设置的maxLength值?
推荐两种实用方式:
- 方式一:抽离配置变量复用(最简洁高效)
将register的配置项单独定义为变量,直接读取变量中的值即可:const TestPage = (props: Props) => { const rhf = useForm(); const fieldConfig = { maxLength: 40, disabled: true }; const testRegister = rhf.register('test', fieldConfig); return ( <div className="text-grayscale-130"> <form> <input type="text" {...testRegister} /> <div>{`maxLength : ${fieldConfig.maxLength}`}</div> </form> </div> ); }; - 方式二:通过表单元数据获取(仅适配复杂场景)
可以通过useForm提供的getFieldState方法获取字段的验证规则元数据,不过这种方式相对繁琐,不如第一种直接。
内容的提问来源于stack exchange,提问作者김경한

