React setState 立即生效的幾種方式?


首先了解一個造成不能立即生效的原因,setState異步的原因是因為react的監聽事件為合成事件,state執行過程中會經歷一個生命周期函數,執行多個setState會被合並,提升性能,下面幾種方式可以避免我們的問題:

  • shouleComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

setState合適同步何時異步?

由React控制的事件處理程序,以及生命周期函數調用setState不會同步更新state 。

React控制之外的事件中調用setState是同步更新的。比如原生js綁定的事件,setTimeout/setInterval等。

 this.setState({ count: this.state.count + 1 });
 this.setState({ count: this.state.count + 1 });
 this.setState({ count: this.state.count + 1 });

 // 執行后結果相當於
 const count = this.state.count;
 this.setState({ count: count + 1 });
 this.setState({ count: count + 1 });
 this.setState({ count: count + 1 });

1、傳遞函數()=>{return state},react提供的參數props保證每次都拿到最新的

// 第一個函數調用更新state,第二個函數是更新完之后的回調。
  this.setState((prevState, props) => {
        return {
         age: prevState.count + 1,
     };
  // 獲取state
   console.log(this.state); // 1
}); 

2、設置setTimeout、setInterval,和事件玄幻有關系

setTimeout(fn,0)的含義是,指定某個任務在主線程最早可得的空閑時間執行,也就是說,盡可能早得執行。它在"任務隊列"的尾部添加一個事件,因此要等到同步任務和"任務隊列"現有的事件都處理完,才會得到執行。

 setTimeout(() => {
   this.setState(prevState => {
      return {
        age: prevState.count + 1,
     };
   });
   // 獲取state
   console.log(this.state); // 1
 }, 0);

3、設置js原生監聽事件addEventListener

原生事件的調用棧就比較簡單了,因為沒有走合成事件的那一大堆,直接觸發click事件,到 requestWork ,在 requestWork里由於 expirationTime === Sync 的原因,直接走了 performSyncWork 去更新,並不像合成事件或鈎子函數中被return,所以當你在原生事件中setState后,能同步拿到更新后的state值。
 handleClick3 = () => {
      this.setState({ count: this.state.count + 1 });
      // 某些條件可能獲取不到最新的值
      console.log(this.state);
   };
   componentDidMount() {
      document.body.addEventListener('btn4', this.handleClick3, false);
   }
詳細代碼如下:
class Demo extends React.Component {
   state = {
      count: 0,
   };

   handleClick0 = () => {
      this.setState({ count: this.state.count + 1 });
      this.setState({ count: this.state.count + 1 });
      this.setState({ count: this.state.count + 1 });
      // 某些條件可能獲取不到最新的值
      console.log(this.state);
   };

   // 1、把對象改為回調函數
   handleClick1 = () => {
      this.setState(prevState => {
         return {
            age: prevState.count + 1,
         };
      });
      // 獲取state
      console.log(this.state); // 1
   };

   // 2、設置setTimeout,setInterval
   handleClick2 = () => {
      setTimeout(() => {
         this.setState(prevState => {
            return {
               age: prevState.count + 1,
            };
         });
         // 獲取state
         console.log(this.state); // 1
      }, 0);
   };

   // 3、設置原生監聽事件,不同調用react的一些生命周期,直接觸發onclick
   handleClick3 = () => {
      this.setState({ count: this.state.count + 1 });
      // 某些條件可能獲取不到最新的值
      console.log(this.state);
   };
   componentDidMount() {
      document.body.addEventListener('btn4', this.handleClick3, false);
   }

   render() {
      return (
         <div>
            <button onClick={() => this.handleClick0()}>按鈕0</button>
            <button onClick={() => this.handleClick1()}>按鈕1</button>
            <button onClick={() => this.handleClick1()}>按鈕2</button>
            <button id="btn4" onClick={() => this.handleClick1()}>
               按鈕3
            </button>
         </div>
      );
   }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM