React中useState绑定的input输入框锁定初始值无法修改
问题根因
这是React受控组件的模式匹配冲突问题:
- 你调用
useState()时没有传入初始值,首次渲染时inputVal的值为undefined - React判定表单组件是否为受控组件的规则是:只要
value属性传入undefined/null,就会把组件归为非受控组件,输入值由DOM原生管理,不受React状态控制 - 首次渲染后你触发输入时,
onChange会调用setInputVal把状态更新为输入的字符串值,组件重渲染时value拿到了有效值,React又会把组件判定为受控组件,由React状态接管值的渲染 - 组件在首次渲染和后续更新时在受控/非受控两种模式间切换,会直接导致输入框值被锁死,无法响应输入操作,控制台一般还会同步抛出相关的模式不匹配警告。
额外注意:type="number"类型的输入框,e.target.value默认返回字符串格式,如果业务需要数值类型,直接存字符串可能导致后续类型计算异常,这不是锁死输入框的原因,但属于配套需要处理的细节。
修复方法
核心原则是保证组件任何渲染时机下,传入input的value都不是undefined/null,始终保持受控模式,具体修改分两步:
- 给
useState传入合法初始值,无预置输入内容时用空字符串作为初始值即可
// 无默认值时初始化为空字符串,保证首次渲染就是受控模式 const [inputVal, setInputVal] = useState('') // 如果有固定初始数值,直接传对应数字即可,比如初始值为0 // const [inputVal, setInputVal] = useState(0)
- 如果存在页面加载后异步拉取数据回填输入框的场景,要避免接口返回的空值(null/undefined)把状态改回非法值,可以给value属性加空值兜底,同时按需处理输入值的类型:
<input type="number" // 兜底处理,避免状态为undefined/null时切换为非受控模式 value={inputVal ?? ''} onChange={(e) => { // 需要存数值类型就取valueAsNumber,空输入时兜底为空字符串 setInputVal(e.target.valueAsNumber || e.target.value) }} />
内容的提问来源于stack exchange,提问作者Denver Dang
相关产品推荐
相关产品推荐

