首頁 > 軟體

React setState是非同步還是同步原理解析

2022-11-17 14:00:48

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非同步同步的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com