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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:09:28