React setState是異步還是同步原理解析
setState異步更新
開發中當組件中的狀態發生瞭變化,頁面並不會重新渲染。我們必須要通過setState來告知React數據已經發生瞭變化,重新渲染頁面。
先來看下面的例子:
constructor() { super(); this.state = { message: "Hello World", }; } changeText() { this.setState({ message: "Hello React", }); console.log(this.state.message); // Hello World }
最終打印的結果是Hello World;
可見setState是異步的操作,我們並不能在執行完setState之後立馬拿到最新的state的結果
那麼為什麼setState設計為異步呢?
setState設計為異步,可以顯著的提升性能
- 如果每次調用setState都進行一次更新,那麼意味著render函數會被頻繁調用,界面重新渲染,這樣效率是很低的;
- 最好的辦法是獲取多個更新,之後進行批量處理;
如果同步更新瞭state,但是還沒有執行render函數,那麼state和props不能保持同步;
state和props不能保持一致性,會在開發中產生很多的問題;(比如,組件嵌套時影響子組件中的狀態)
如何獲取異步的結果
setState的回調
setState接受兩個參數:第二個參數是一個回調函數,這個回調函數會在更新後會執行;
changeText() { this.setState({ message: "Hello React", },()=>{ console.log('-----',this.state.message); // Hello React }); }
也可以在生命周期函數中獲取:
componentDidUpdate(prevProps, prevState, snapshot){ console.log(this.state.message);// Hello React }
setState一定是異步的嗎?
React18版本之前
其實可以分成兩種情況:
- 在組件生命周期或React合成事件中,setState是異步的;
- 在setTimeout或者原生DOM事件中,setState是同步的
驗證一:在setTimeout中的更新:
setTimeout(() => { this.setState({ message: "Hello React", }); console.log(this.state.message); // Hello React }, 0);
驗證二:原生DOM事件:
componentDidMount() { const btnEl = document.querySelector("#btn"); btnEl.addEventListener("click", () => { this.setState({ message: "Hello React", }); console.log(this.state.message); // Hello React }); }
React18版本之後
setState默認是異步的
- 在React18之後,默認所有的操作都被放到瞭批處理中(異步處理)
如果希望代碼可以同步拿到,則需要執行特殊的flushSync操作:
import { flushSync } from "react-dom"; changeText() { flushSync(() => { this.setState({ message: "Hello React", }); }); console.log(this.state.message); // Hello React }
以上就是React setState是異步還是同步原理解析的詳細內容,更多關於React setState異步同步的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 代碼解析React中setState同步和異步問題
- 深入理解React State 原理
- React Class組件生命周期及執行順序
- React的三大屬性你都知道嗎
- 關於React中setState同步或異步問題的理解