解決react中useState狀態(tài)異步更新的問題
疑惑
相信剛開始使用react函數(shù)組件的小伙伴也遇到過一個坑,就是 useState 更新狀態(tài)是異步更新的,但是react 并沒有提供關(guān)于這個問題的解決方案。那我們能否使用自己的方法來解決這個問題呢?答案肯定是可以的。
狀態(tài)異步更新帶來的問題
就拿一個比較常見的場景來說。在react項目中,我們想在關(guān)閉對話框后再去處理其他業(yè)務(wù)。但是 useState 的狀態(tài)是異步更新的。我們通過setVisible 更新狀態(tài)后,狀態(tài)并沒有立馬更新,這也就說明對話框并沒有關(guān)閉,這也就造成了我們后面的邏輯在對話框沒關(guān)閉時就執(zhí)行了,這并不是我們想要的結(jié)果。下面來看我是如何來巧妙的解決這個問題的。
問題示例
// 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>
)
}
下面是上面組件運行結(jié)果:

點擊按鈕后的運行結(jié)果:

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

問題解決
類組件的解決方案
在類組件中,我們可以在 setState(newstate,callback) 第二個參數(shù)傳一個回調(diào)來處理本次狀態(tài)更新后的一些其他業(yè)務(wù)。但是在函數(shù)組件中我們?nèi)绾蝸斫鉀Q這個問題呢?來看以下方案,也是我們這篇文章主要想為大家解決的問題。
函數(shù)組件的解決方案
解決該問題使用到的 api有:useEffect,Promise
1.在項目源碼目錄下創(chuàng)建文件夾 customHooks,然后在 customHooks/useCallbackState.ts中編寫如下代碼:
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)
})
}
此時的運行結(jié)果如下:

注意:謹(jǐn)慎使用,打印可以看出,其實狀態(tài)并沒有真正完成更新。依然達(dá)不到類組件callback的效果。
其他解決方案
如果真的存在上面這種需求,我們可以使用類組件,或者使用 setTimeout來解決上面的問題,把對話框關(guān)閉后的業(yè)務(wù)寫在延時的回調(diào)中就行了,延時個 500 毫秒 狀態(tài)一定更新完畢了,個人感覺這個方法不太好,還是推薦使用類組件來解決上述問題。
結(jié)尾
到此這篇關(guān)于解決react中useState狀態(tài)異步更新的問題的文章就介紹到這了,更多相關(guān)react useState狀態(tài)異步更新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react-native android狀態(tài)欄的實現(xiàn)
這篇文章主要介紹了react-native android狀態(tài)欄的實現(xiàn),使?fàn)顟B(tài)欄顏色與App顏色一致,使用戶界面更加整體。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
React 無狀態(tài)組件(Stateless Component) 與高階組件
這篇文章主要介紹了React 無狀態(tài)組件(Stateless Component) 與高階組件,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
使用React-Window實現(xiàn)虛擬滾動效果的示例代碼
React-Window?是一個為?React?應(yīng)用程序中高效渲染大數(shù)據(jù)集而設(shè)計的庫,它基于窗口化或虛擬化的原則運行,本文將使用React-Window實現(xiàn)虛擬滾動效果,感興趣的可以了解下2024-01-01
react高階組件經(jīng)典應(yīng)用之權(quán)限控制詳解
在React中,高階組件是重用組件邏輯的一項高級技術(shù)。下面這篇文章主要給大家介紹了關(guān)于react高階組件經(jīng)典應(yīng)用之權(quán)限控制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09
react源碼層深入刨析babel解析jsx實現(xiàn)
同作為MVVM框架,React相比于Vue來講,上手更需要JavaScript功底深厚一些,本系列將閱讀React相關(guān)源碼,從jsx -> VDom -> RDOM等一些列的過程,將會在本系列中一一講解2022-10-10

