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

react-hook-form真实设备验证失效,restrictValue函数无法限制输入

问题解决步骤

1. 修复输入限制不生效的核心问题

根源分析

  • 使用type="number"时,maxLength属性对原生input无效,真实移动端设备的数字键盘允许输入负号、小数点等符号,导致自定义的restrictValue函数无法正确处理这些输入。
  • 在react-hook-form的validate规则里调用setValue是错误用法:验证阶段仅用于判断值是否合法,直接修改表单状态会导致状态更新时机混乱,真实设备因事件触发顺序不同,就会出现失效情况。

解决方案

步骤1:调整input类型与键盘触发

把type="number"改成type="text",同时通过inputMode="numeric"触发移动端数字键盘,配合pattern="[0-9]*"确保输入仅为数字:

<FormInputText
  // ...其他props
  type="text" // 替换原有的type="number"
  inputProps={{
    maxLength: 2,
    inputMode: 'numeric', // React属性为驼峰式,不是小写的inputmode
    pattern: '[0-9]*'
  }}
/>

步骤2:正确处理输入格式化

用useWatch监听输入变化,在值改变时自动格式化,而非在验证阶段修改:

import { useWatch } from 'react-hook-form';

// 组件内部
const monthValue = useWatch({ control, name: 'month' });

useEffect(() => {
  // 修正正则:全局替换所有非数字字符(原正则/[^0-9]*/g无效,会匹配空串)
  const formattedValue = monthValue.replace(/[^0-9]/g, '');
  const trimmedValue = formattedValue.slice(0, 2);
  
  // 仅在值变化时更新,避免无限循环
  if (trimmedValue !== monthValue) {
    setValue('month', trimmedValue, { 
      shouldValidate: true, // 格式化后自动触发验证
      shouldDirty: true 
    });
  }
}, [monthValue, setValue]);

步骤3:简化验证规则

去掉冗余的notNumber验证,合并成一个validMonth规则,避免重复逻辑:

rules={{
  required: '请输入月份',
  validate: {
    validMonth: (value) => {
      const parsedMonth = parseInt(value, 10);
      return (!isNaN(parsedMonth) && parsedMonth > 0 && parsedMonth <= 12) 
        || '请输入1-12之间的有效月份';
    }
  }
}}

2. 修复构建失败问题

之前构建失败是因为inputProps里用了小写的inputmode,React的DOM属性要求驼峰式的inputMode,TypeScript会因类型不匹配报错。改成上面的inputMode: 'numeric'即可解决。

额外优化点

  • 修正restrictValue函数的正则:原/[^0-9]*/g逻辑错误,应替换为/[^0-9]/g来全局移除所有非数字字符。
  • 若你的FormInputText是基于Controller封装的自定义组件,需确保它正确将inputProps传递给底层的Material-UI TextField组件。

内容的提问来源于stack exchange,提问作者Manju

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:43:13