如何合理使用React setState

1、不要直接修改 state(狀態)

this.state.Arr.splice(...)
this.setState({
    Arr:this.state.Arr  
})
複製代碼

這樣雖然能夠生效,但應該遵循immutable的原則而儘可能避免直接修改state中的數據,能夠改成javascript

const Arr = [...this.state.Arr]
Arr.splice(...)
this.setState({
   Arr
})
複製代碼

2、setState異步更新

先來看一個例子,console.log打印的結果分別是什麼java

this.state = {
  num: 0,
}

componentWillMount() {
    this.setState({
      num: this.state.num + 1,
    });
    console.log(this.state.num);
    
    this.setState({
      num: this.state.num + 1,
    });
    console.log(this.state.num);
}

render() {
    console.log(this.state.num);
}
複製代碼

是否是認爲會是: 1 2 2,可是打印出來的是0 0 1。瀏覽器

再來一個簡單的例子。bash

// 錯誤
this.setState({
  counter: this.state.counter + this.props.increment
})
複製代碼

咱們會發現,以上代碼可能致使 counter(計數器) 更新失敗。綜上可知,state(狀態) 更新多是異步的,React.js 爲了優化性能,有可能會將多個 setState() 調用合併爲一次更新。異步

由於 this.props 和 this.state 多是異步更新的,因此你不能依賴他們的值計算下一個state(狀態)。函數

咱們先經過一張圖瞭解一下它的隊列機制。性能

setState方法經過一個隊列機制實現state更新,當執行setState的時候,會將須要更新的state合併以後放入狀態隊列,而不會當即更新this.state(能夠和瀏覽器的事件隊列類比)優化

如何解決state(狀態) 異步更新的問題,從而拿到正確的數據呢。ui

  • setTimeout
setTimeout(() => {
  this.setState({
    num: this.state.num + 1,
  });
  console.log(this.state.num);  // 1
  this.setState({
    num: this.state.num + 1,
  });
  console.log(this.state.num);  // 2
}, 0);
複製代碼
  • setState的回調函數 setState能夠接受兩張參數,對象和函數,對於某些異步更新的問題能夠在setState傳入回調函數
// 例1的異步處理。setState自己還能夠接收第二個參數,解決setState更新完後拿到數據觸發,因此第二個參數是一個回調函數
this.setState(((prevState) => {
   prevState.num++;
}), () => {
  // 拿到數據後能夠作更新視圖等等操做
  console.log(this.state.num); // 2
});
this.setState(((prevState) => {
    prevState.num++;
}), () => {
  console.log(this.state.num); // 2
});

// 例2的異步處理,第一個參數是原始state,等同於this.state,第二個參數是父組件傳遞的屬性
this.setState((prevState, props) => ({
  //prevState:在改變state中的數據以前,打印出當前的state
  counter: prevState.counter + props.increment 
}))
複製代碼
  • Promise封裝
setStatePromise(cb) {
    return new Promise(((resolve, reject) => {
      this.setState(cb, resolve);
    }));
}

this.setStatePromise(() => {
    return ({
      dataArray: [1, 2, 3, 4],
      total: 10
    })
}).then(() => {
  console.log(this.state.dataArray); //[1, 2, 3, 4]
});
複製代碼

setState 合併

上面咱們進行了屢次的setState,可是實際上組件只會從新渲染一次,而不是屢次;這是由於在 React.js 內部會把 JavaScript 事件循環中的消息隊列的同一個消息中的 setState 都進行合併之後再從新渲染組件。所以,在使用 React.js 的時候,並不須要擔憂屢次進行 setState 會帶來性能問題。this

相關文章
相關標籤/搜索