React中onBlur事件触发后useState对象值未更新的问题求助
问题:React useState更新后控制台未显示最新值
我有一个MyTextField组件,代码如下:
<MyTextField type={inpValues.emailID.type} label={inpValues.emailID.label} name={inpValues.emailID.name} placeholder={inpValues.emailID.placeHolder} required={inpValues.emailID.required} error={inpValues.emailID.error} helperText={inpValues.emailID.helperText} handleOnBlur={(event) => { //console.log("Call HandleOnBlur"); setInpValues({...inpValues, email:{ ...inpValues.emailID, value:event.target.value }}) HandleEmailOnBlur(inpValues.emailID.value) } } value={inpValues.emailID.value} ></MyTextField>
HandleEmailOnBlur函数
const HandleEmailOnBlur = (emailID) =>{ if(emailID.trim().length > 0){ let email = emailID; emailValidation(email) } if(inpValues.emailID.error === false){ //.... 若为false则通过AXIOS调用服务器 } } function emailValidation(email) { console.log('Email Validation Called, Email = '+ email) if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) { return ('') } else { //以下代码已执行 setInpValues({ ...inpValues, emailID: { ...inpValues.emailID, error: true, helperText: 'Please enter valid Email ID' // 浏览器上可看到此文本 } }) } //但在控制台查看对象值时并未更新,原因是什么? console.table(inpValues) }
我能调用emailValidation(email)函数,它会设置error:true, helperText:'Please enter valid Email ID',helperText在浏览器上已经更新,但useState对象的值在控制台里没变化。
我试过用prevState写法,结果还是一样:
setInpValues(prevInpValues => ({ ...prevInpValues, emailID: { ...prevInpValues.emailID, error: true, helperText: 'Please enter valid Email ID' } }) )
解答
这是React状态更新的异步特性导致的:
状态更新是异步操作
useState的setInpValues不会立刻修改当前作用域里的inpValues变量。你在调用setInpValues后立刻打印inpValues,拿到的还是更新前的旧值,因为状态更新还没完成。UI更新但控制台没显示的原因
React会在状态更新完成后触发组件重渲染,UI能拿到最新状态并更新,但当前函数作用域里的inpValues是闭包捕获的旧值,不会同步改变。查看最新状态的方法
- 用
useEffect监听状态变化:
每次useEffect(() => { console.table(inpValues); }, [inpValues]);inpValues更新后,都会自动打印最新值。 - 在状态更新前先保存新值并打印:
function emailValidation(email) { console.log('Email Validation Called, Email = '+ email) if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) { return ('') } else { const newState = { ...inpValues, emailID: { ...inpValues.emailID, error: true, helperText: 'Please enter valid Email ID' } }; setInpValues(newState); console.table(newState); // 打印即将更新的最新状态 } }
- 用
修复handleOnBlur里的旧值问题
你在handleOnBlur里先更新状态再传值,同样会拿到旧的inpValues.emailID.value,改成直接用事件里的新值:handleOnBlur={(event) => { const newValue = event.target.value; setInpValues(prev => ({...prev, emailID:{ ...prev.emailID, value: newValue }})) HandleEmailOnBlur(newValue) }}
内容的提问来源于stack exchange,提问作者Liam neesan
相关产品推荐
相关产品推荐

