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

如何阻止非数字字符输入到React+TypeScript输入框中

解决方案

核心问题分析

你当前的问题源于两个点:

  1. 输入框的onChange同时触发了两次状态更新,导致逻辑冲突;
  2. 非法输入时直接清空状态,而非保留合法内容,造成输入框清空或显示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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:27:42