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-UITextField组件。
内容的提问来源于stack exchange,提问作者Manju
相关产品推荐
相关产品推荐

