React中number类型输入框作为受控组件触发事件警告的求助
React数字输入框受控组件触发合成事件池警告的解决办法
这个警告的核心原因是React的合成事件池机制:React会复用合成事件对象来提升性能,事件处理函数执行完毕后,事件对象的属性会被重置为null。你在setUser的更新回调里访问event.target时,原事件已经被回收了,所以触发警告。
数字输入框会触发这个问题,是因为你把numOfQs初始值设为数字0,但输入框返回的event.target.value是字符串类型,React在同步值的时候会触发额外的状态校验,导致更新回调执行时事件已经被回收;而其他输入类型(比如文本框)因为值都是字符串,没有这个额外的类型差异触发的时机问题,所以没显现警告。
解决办法(推荐第一种)
1. 提前提取事件中的关键属性
在事件处理函数里,先把需要的name和value取出来,再执行状态更新,这样就不会依赖已经被回收的事件对象,同时还能处理数字类型转换的问题:
export default function Form() { const [user, setUser] = useState({ name: "", numOfQs: 0 }) console.log(user) function handleUserDataChange(event) { // 提前提取事件属性,脱离对原事件对象的依赖 const { name, value } = event.target; // 针对数字输入框,把字符串值转为数字类型 const inputValue = name === "numOfQs" ? Number(value) : value; setUser(prevUser => { return { ...prevUser, [name]: inputValue } }) } return ( <> <input type="text" placeholder="username" name="name" value={user.name} onChange={handleUserDataChange} /> <input type="number" name="numOfQs" value={user.numOfQs} onChange={handleUserDataChange} /> </> ) }
2. 使用event.persist()(不推荐)
调用这个方法可以让React不把事件对象放回池子里,这样就能在更新回调里访问事件属性,但会影响性能,不建议在生产环境使用:
function handleUserDataChange(event) { event.persist(); setUser(prevUser => { return { ...prevUser, [event.target.name]: event.target.name === "numOfQs" ? Number(event.target.value) : event.target.value } }) }
额外提醒:数字输入框的value默认是字符串类型,如果你希望状态里存的是数字,一定要手动转换,否则会出现类型不一致的问题(比如初始值是0,输入后变成字符串"1")。
内容的提问来源于stack exchange,提问作者user18457520
相关产品推荐
相关产品推荐

