React中setState方法說明

setState跟新數據是同步還是非同步?

setState跟新數據是非同步的。
如何用程式碼表現出來是非同步的。
點擊按鈕更新數據,然後去列印這個值看一下

setState跟新數據是非同步的

class Father extends React.Component{
  state = {
   num:0
  }
  addHandler = () => { 
    this.setState({
      num: 100
    })
    console.log('state中的值',this.state.num)
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p>顯示的值 {this.state.num }</p>
      </div>
    )
  }
}
ReactDOM.render(
  <Father></Father>,
  document.getElementById('root')
)

我們發現

當我們使用setState更新數據時候,
然後立刻去獲取更新後的值,我們發現不是我們更新後的值。
而是更新前的值。
這就說明了setState跟新數據是非同步的

因此需要注意的點

由於 setState 跟新數據是非同步的。
因此 setState 後面的程式碼不要依賴於setState前面的。

同一個方法多次調用 setState會怎麼樣

class Father extends React.Component{
  state = {
   num:0
  }
  addHandler = () => { 
    <!-- 第一調用 -->
    this.setState({
      num: this.state.num+1
    })
    console.log('state中的值', this.state.num)
    
    <!-- 第二次調用 -->
    this.setState({
      num: this.state.num + 1
    })
    console.log('state中的值', this.state.num)
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p>顯示的值 {this.state.num }</p>
      </div>
    )
  }
}

我們的結論

在同一個方法中我們調用了兩次setState.
但是最後介面上顯示的不是2;0+1+1=2
而是顯示的1
也就是說雖然多次調用setState,但是最終只會執行一次。 
所以只會觸發一次渲染介面。所以介面上顯示的是1
由於介面只觸發一次,所以render函數也只會觸發一次

為什麼多次調用setState最終只會觸發一次渲染介面

這樣做的目的是為了性能的考慮。
比如說你寫了一個循環,循環了1000次;
設計的時候如果讓setState執行1000次;
這樣太浪費性能了。
完全可以讓開發者將最後的結果進行展示。

所以React並不會將setState執行1000次
而是只會執行一次。 render函數也只會執行一次。

非要讓setState多次執行怎麼辦?

有沒有這樣的場景?
第二次的setState需要依賴第一次的setState的結果
舉個簡單的例子:第一次數字從0變為1,第二次1變為10
這個時候我們怎麼辦了?
比著急,有解決的辦法

setState 推薦語法

setState((state, props) => { 
    參數state,表示最新的state
    參數props,表示最新的props
})
需要的是這種語法也是非同步的哈

使用推薦語法實現setState多次執行

class Father extends React.Component{
  state = {
   num:0
  }
  addHandler = () => { 
    <!-- 在這個方法中我們多次調用了setState  -->
    this.setState((state, props) => { 
      // state 
      // props
      return {
        num: state.num+1
      }
    })
    this.setState((state, props) => {
      // state 
      // props
      return {
        num: state.num + 10
      }
    })
    console.log('state中的值', this.state.num)
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p>顯示的值 {this.state.num }</p>
      </div>
    )
  }
}

setState第二個參數的誕生

剛剛我們在前面發現console.log獲取的值
不是數據更新的後的值。
而是初始值。我們也說了
由於 setState 跟新數據是非同步的。
因此 setState 後面的程式碼不要依賴於setState前面的。
如果我們想獲取 setState更新後的值怎麼辦了?
這個時候我們就需要使用setState的第二個參數。

setState第二個參數的場景
在狀態更新完成(介面完成重新渲染)後立刻執行某一個操作
ps:需要注意的的是不可以不會頁面中的dom
ps:需要注意的的是不可以不會頁面中的dom
this.setState(
    (state, props) => {
        return {}
    },
    ()=>{
        console.log('介面完成重新渲染)後立刻執行某一個操作')
    }
)

setState第二個參數的使用

class Father extends React.Component{
  state = {
   num:0
  }
  addHandler = () => { 
    this.setState(
      (state, props) => {
        return {
          num: state.num + 1
        }
      },
      () => { 
        console.log('獲取setState跟新後的值', this.state.num)
        console.log('dom節點',document.getElementById('#name') )
        console.log('cont', document.title)
      }
    )
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p id='name'>顯示的值 {this.state.num }</p>
      </div>
    )
  }
}
ReactDOM.render(
  <Father></Father>,
  document.getElementById('root')
)

Tags: