解決react中useState狀態(tài)異步更新的問(wèn)題
疑惑
相信剛開(kāi)始使用react函數(shù)組件的小伙伴也遇到過(guò)一個(gè)坑,就是 useState 更新?tīng)顟B(tài)是異步更新的,但是react 并沒(méi)有提供關(guān)于這個(gè)問(wèn)題的解決方案。那我們能否使用自己的方法來(lái)解決這個(gè)問(wèn)題呢?答案肯定是可以的。
狀態(tài)異步更新帶來(lái)的問(wèn)題
就拿一個(gè)比較常見(jiàn)的場(chǎng)景來(lái)說(shuō)。在react項(xiàng)目中,我們想在關(guān)閉對(duì)話框后再去處理其他業(yè)務(wù)。但是 useState 的狀態(tài)是異步更新的。我們通過(guò)setVisible 更新?tīng)顟B(tài)后,狀態(tài)并沒(méi)有立馬更新,這也就說(shuō)明對(duì)話框并沒(méi)有關(guān)閉,這也就造成了我們后面的邏輯在對(duì)話框沒(méi)關(guān)閉時(shí)就執(zhí)行了,這并不是我們想要的結(jié)果。下面來(lái)看我是如何來(lái)巧妙的解決這個(gè)問(wèn)題的。
問(wèn)題示例
// App.tsx
import {useState} from "react"
export default ()=>{
const [num,setNum]=useState(0)
const add=()=>{
console.log("更新前",num)
setNum(num+1)
console.log('更新后',num)
}
return(
<div className='App'>
<p>{num}</p>
<button onClick={add}>num++</button>
</div>
)
}
下面是上面組件運(yùn)行結(jié)果:

點(diǎn)擊按鈕后的運(yùn)行結(jié)果:

當(dāng)我們點(diǎn)擊按鈕時(shí)的打印結(jié)果:

問(wèn)題解決
類(lèi)組件的解決方案
在類(lèi)組件中,我們可以在 setState(newstate,callback) 第二個(gè)參數(shù)傳一個(gè)回調(diào)來(lái)處理本次狀態(tài)更新后的一些其他業(yè)務(wù)。但是在函數(shù)組件中我們?nèi)绾蝸?lái)解決這個(gè)問(wèn)題呢?來(lái)看以下方案,也是我們這篇文章主要想為大家解決的問(wèn)題。
函數(shù)組件的解決方案
解決該問(wèn)題使用到的 api有:useEffect,Promise
1.在項(xiàng)目源碼目錄下創(chuàng)建文件夾 customHooks,然后在 customHooks/useCallbackState.ts中編寫(xiě)如下代碼:
import { useState, useRef, useEffect } from 'react';
export default(initState: any)=>{
const stateRef = useRef(null as any);
const [state, setState] = useState(initState);
useEffect(() => {
stateRef.current && stateRef.current(state);
}, [state]);
return [
state,
(newState:typeof initState):Promise<typeof initState>=>
new Promise(rel=>{stateRef.current=rel;setState(newState)})
];
}
2.在上面的 App.tsx中使用上面的自定義hook
import useCallbackState from "@/customHooks/useCallbackState"
const [num,setNum]=useCallbackState(0)
const add=()=>{
console.log('更新前',num)
setNum(num+1)
.then((newNum:any)=>{
console.log('更新后',newNum)
// console.log(num)
})
}
此時(shí)的運(yùn)行結(jié)果如下:

注意:謹(jǐn)慎使用,打印可以看出,其實(shí)狀態(tài)并沒(méi)有真正完成更新。依然達(dá)不到類(lèi)組件callback的效果。
其他解決方案
如果真的存在上面這種需求,我們可以使用類(lèi)組件,或者使用 setTimeout來(lái)解決上面的問(wèn)題,把對(duì)話框關(guān)閉后的業(yè)務(wù)寫(xiě)在延時(shí)的回調(diào)中就行了,延時(shí)個(gè) 500 毫秒 狀態(tài)一定更新完畢了,個(gè)人感覺(jué)這個(gè)方法不太好,還是推薦使用類(lèi)組件來(lái)解決上述問(wèn)題。
結(jié)尾
到此這篇關(guān)于解決react中useState狀態(tài)異步更新的問(wèn)題的文章就介紹到這了,更多相關(guān)react useState狀態(tài)異步更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在create-react-app中使用css modules的示例代碼
這篇文章主要介紹了在create-react-app中使用css modules的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
React學(xué)習(xí)之JSX與react事件實(shí)例分析
這篇文章主要介紹了React學(xué)習(xí)之JSX與react事件,結(jié)合實(shí)例形式分析了React中JSX表達(dá)式、屬性、嵌套與react事件相關(guān)使用技巧,需要的朋友可以參考下2020-01-01
react-native使用leanclound消息推送的方法
這篇文章主要介紹了react-native使用leanclound消息推送的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08

