ReactではsetStateは即座に反映されない

ReactではsetStateで変更された内容はどうやら、renderされるまで反映されないらしい。
試しに以下のコードを試してみる。

class SetStateSample extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      val: ""
    }
  }
  handleClick() {
    this.setState({val: "test"})
    alert(this.state.val)  // ""
  }
  render() {
   return (
     <h1 onClick={this.handleClick.bind(this)}}>{this.state.val}</h1>
     )
   }
}

上の例ではsetState前の値がalertにより表示される。

そのため、初回のalertでは初期値が表示される。

alertの時点でthis.state.valの値を正しく取得したい場合は以下のようにhandleClickを修正する。

handleClick() {
    var new_val = "test"
    this.setState({val: new_val})
    alert(new_val)  // "test"
}

つまり変数に入れてalertに入れるだけ。
これで想定したとおりの処理になる。

setState直後にstateが更新されない原因

React公式ページに以下の通りの記載がある。
https://ja.reactjs.org/docs/faq-state.html

setState 呼び出しは非同期です。呼び出し直後から this.state が新しい値を反映することを期待しないでください。もし現在の state に基づいた値を計算する必要がある場合は、オブジェクトの代わりに更新関数を渡してください。

https://ja.reactjs.org/docs/faq-state.html

setStateの呼び出しが非同期なので、setState直後には反映されていなかったんですね。
仮に現在のstateをもとに新しいstateに更新する場合は以下のように記載しましょう。

  handleClick() {
    this.setState((state) => 
      return { val: state.val + "test" }
    });
  }

コメント