React-hook-form搭配MUI TextField使用input mask时出现非受控报错
问题描述
使用 react-hook-form 的 Controller 组件搭配 react-input-mask 与 Material UI TextField 组件时,表单提交阶段无法访问校验错误信息,参考同类方案设置 defaultValue 后问题未解决。移除 InputMask 直接使用 TextField 时,表单校验功能可正常运行。
异常场景实现代码
import { TextField } from "@mui/material"; import { Controller } from "react-hook-form"; import InputMask from "react-input-mask"; const InputCustom = ({ control, errorFieldMessage, name, mask, label, }: any) => { return ( <Controller name={name} control={control} defaultValue="" render={({ field: { onChange, value } }) => ( <InputMask mask={mask} value={value} onChange={onChange}> {(inputProps: any) => ( <TextField error={!!errorFieldMessage} helperText={errorFieldMessage} label={label} variant="outlined" type="text" fullWidth required {...inputProps} /> )} </InputMask> )} /> ); };
正常场景实现代码(移除InputMask后)
import { TextField } from "@mui/material"; import { Controller } from "react-hook-form"; import InputMask from "react-input-mask"; const InputCustom = ({ control, errorFieldMessage, name, mask, label, }: any) => { return ( <Controller name={name} control={control} defaultValue="" render={({ field: { onChange, value } }) => ( <TextField error={errorFieldMessage} label={label} variant="outlined" type="text" fullWidth required onChange={onChange} value={value} /> )} /> ); };
根因分析
问题出在字段状态绑定逻辑不完整:
- 仅将
Controller字段对象中的onChange、value绑定到InputMask,丢失了onBlur、ref等react-hook-form依赖的状态同步属性,导致输入值无法实时同步到表单内部状态,校验触发时无法获取字段最新值,自然不会返回对应错误。 - 错误状态依赖外部传入的
errorFieldMessage,没有和Controller管理的字段内部校验状态绑定,状态同步链路断裂时错误信息无法正常渲染。
修复方案
直接从 Controller 的 render 参数中获取完整字段对象与字段校验状态,不要手动拆分绑定字段属性,也不需要从外部传入错误属性:
import { TextField } from "@mui/material"; import { Controller } from "react-hook-form"; import InputMask from "react-input-mask"; const InputCustom = ({ control, name, mask, label, }: any) => { return ( <Controller name={name} control={control} defaultValue="" render={({ field, fieldState: { error } }) => ( <InputMask mask={mask} {...field}> {(inputProps: any) => ( <TextField error={!!error} helperText={error?.message} label={label} variant="outlined" type="text" fullWidth required {...inputProps} /> )} </InputMask> )} /> ); };
关键修改说明
- 将
Controller返回的完整field对象(包含onChange、onBlur、value、ref、name全量属性)直接展开传给InputMask,保证所有状态同步事件、值绑定都能正确透传,不需要手动拆分绑定单个属性。 - 错误状态、错误提示文案直接从
Controller提供的fieldState.error中获取,和表单内部校验状态保持同源,不需要父组件额外传入错误相关属性。 TextField不需要手动绑定onChange、value属性,InputMask透传的inputProps已经包含正确绑定的属性,直接展开即可生效。
内容的提问来源于stack exchange,提问作者Bruno
相关产品推荐
相关产品推荐

