在最近的开发中我写了这样一段代码:
const handleTestLogin = () => {
setUserInfo({
token: '1',
uuid: '1',
})
handleCustomLogin()
}而 handleCustomLogin 这个函数中则使用了 userInfo 这个 state,结果 setUserInfo 却没有生效。
这是因为 react 的 useState 是每次绘制更新的异步函数,这是为了性能的考虑。
比如:
const {name, setName} = useState()
setName("1")
setName("2")这样的代码,通过每次绘制更新,避免了无意义的更新值,而只使用最终值 "2"。
因此,在一次绘制周期中,无论怎么使用 set 函数,这个 state 的值永远都不会更新。
要解决这个问题有几种解决方式:
第一种:创建新变量
const handleTestLogin = () => {
const newInfo = {
token: '1',
uuid: '1',
}
handleCustomLogin(newInfo)
}
const handleCustomLogin = (info: unknown) => {
// 使用info参数执行逻辑
setUserInfo(info)
}第二种:使用 带回调的set函数
const handleTestLogin = async () => {
setUserInfo(prevUserInfo => {
const newUserInfo = {
token: '1',
uuid: '1',
}
// 在这里处理更新后的逻辑
setTimeout(() => {
console.log('userInfo updated', newUserInfo)
handleCustomLogin()
}, 100)
return newUserInfo
})
}第三种:使用 useEffect
这个方法本质上是在下一次渲染周期内执行本应上个周期执行的工作。
const handleTestLogin = async () => {
setUserInfo({
token: '1',
uuid: '1',
})
}
useEffect(() => {
if (userInfo.token) {
handleCustomLogin()
}
}, [userInfo])第四种:直接修改 state(不推荐,不规范)
通过使用 userInfo.token = "" 这样的代码,相当于直接修改 state 的引用对象的值,因此可以做到立即更新。但这样不会触发 react 的正常更新流程,可能引起 UI 渲染的 bug,不推荐使用。