iT邦幫忙

2

React 中 setState 的踩雷與解決方式

挑戰 React 第十四篇

上篇我們了解 setState 為非同步,而此篇將會舉一個setState踩雷的例子並且告訴大家如何改進。

預先理解準備

上篇程式碼,當我們按了按鈕一次,UI 數字就會跟著 +1

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

render() {
    return (
      <div>
        <div>counter - {this.state.count}</div>
        <button onClick={() => this.incrementFive()}>button</button>
      </div>
    )
  }

實作範例

把新增的 increment 方法放進 function FiveIncrement 呼叫五次

increment() {
    this.setState({
       count: this.state.count + 1 
    },
    () => {
        console.log('callback value', this.state.count)
    })
    console.log(this.state.count);
  }

  incrementFive() {
    this.increment();
    this.increment();
    this.increment();
    this.increment();
    this.increment();
  }
  
  render() {
    return (
      <div>
        <div>counter - {this.state.count}</div>
        <button onClick={() => this.incrementFive()}>button</button>
      </div>
    )
  }
}

預期按按鈕一次等於呼叫五次應該得到數字5,為何卻得到數字 1?

官方文檔解釋

React 可以將多個 setState() 呼叫批次處理為單一的更新,以提高效能。

什麼意思呢?

以上方程式碼舉例: incrementFive(),React為了提高效能,只會呼叫一次 setState()也就是只呼叫一次increment(),因此數字才會只增加 1。

解決辦法

preState 取得上一個 state,而不是用 this.state

increment() {
    this.setState(prevState => ({
      count: prevState.count + 1
    }))
    console.log(this.state.count);
}
  • 確認按了一次按鈕,數字更新為 5
  • 再按一次,數字更新為 10

若要取得上一個 state + props 來計算怎麼做?

程式碼大概會長以下這樣:

this.setState((prevState, props) => ({
      count: prevState.count + addValue(props)
    }))

學習心得與另一個解決方式

此篇其實是在一個 youtube 看到的範例,過去沒有發現是因為我都把 setState 這個動作當作一個聰明的組件在執行 ; 同時也會新增一個笨的組件當作 UI 的部分。

以目前我們公司專案,會有以下兩個組件:

  1. SmartCounter.js 做較複雜的動作 ex. setState
  2. DumbCounter.js 簡單的動作 ex. UI 呈現

DumbCounter 會接收來自 SmartCounter 的 setState 資料,且因為是由上而下的資料流,此時子組件的DumbCounter 會把來自父組件 SmartCounter 的 state 的資料變成 props,近而比較好利用。


尚未有邦友留言

立即登入留言