如何阻止非数字字符输入到React+TypeScript输入框中
解决方案
核心问题分析
你当前的问题源于两个点:
- 输入框的
onChange同时触发了两次状态更新,导致逻辑冲突; - 非法输入时直接清空状态,而非保留合法内容,造成输入框清空或显示
NaN。
具体修改步骤
1. 重构handleNumericInput函数(App.tsx)
修改函数逻辑,直接过滤非法字符,只保留数字和最多一个小数点,确保输入始终合法:
// handleNumericInput function const handleNumericInput = ( e: React.ChangeEvent<HTMLInputElement>, measurementType: "metric" | "us", allowDecimal: boolean = true // 可选参数,控制是否允许小数 ) => { const { name, value } = e.target; // 过滤非法字符:允许数字+可选小数点(如果开启) let cleanedValue = allowDecimal ? value.replace(/[^0-9.]/g, '') : value.replace(/[^0-9]/g, ''); // 确保只有一个小数点(如果开启小数) if (allowDecimal) { cleanedValue = cleanedValue.replace(/(\..*)\./g, '$1'); } // 转换为数字,空字符串转为0 const numericValue = cleanedValue === '' ? 0 : Number(cleanedValue); // 更新对应状态 if (measurementType === "metric") { setMetricMeasurement(prev => ({ ...prev, [name]: numericValue })); } else { setUsMeasurement(prev => ({ ...prev, [name]: numericValue })); } };
2. 修正输入框组件(Metric.tsx)
移除重复的状态更新调用,优化value显示逻辑,修正pattern属性:
<input className='m-3 bg-slate-100 border w-full h-10 border-slate-300 rounded pl-1' placeholder="cm" inputMode="numeric" type='text' pattern="^\d*\.?\d*$" // 匹配数字(含可选小数)的正则 value={metricMeasurement.heightInCentimetres === 0 ? '' : metricMeasurement.heightInCentimetres.toString()} name="heightInCentimetres" onChange={(e) => handleNumericInput(e, "metric")} // 仅保留统一的处理函数 />
额外优化(针对整数输入场景)
如果是年龄、英尺这类只能输入整数的字段,调用函数时传入allowDecimal: false即可:
<input // 其他属性 placeholder="年龄" onChange={(e) => handleNumericInput(e, "metric", false)} />
效果说明
修改后,用户输入非数字字符时会被自动过滤,输入框只会显示合法的数字内容,不会出现清空或NaN的情况,同时保留了text类型输入框的占位符功能。
内容的提问来源于stack exchange,提问作者ryanl
相关产品推荐
相关产品推荐

