33
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ReactのComponent.setStateによるstateの書き換えは非同期処理である

Last updated at Posted at 2019-07-12

ReactのComponent.setStateによるstateの書き換えは非同期処理である

Reactはパフォーマンス最適化のために、setStateが呼ばれたからと言って、実際のstateを即書き換えるわけではありません。
stateの更新はReact内部でよろしくまとめられて非同期で行われます。
例えば、以下のコードはうまく動いてくれません。

// this.state.hoge = 'fuga'の状態とします。
this.setState({
  hoge:'piyo';
});
console.log(this.state.hoge);//出力されるのはpiyoではなくfuga

困りそうなケースと対応策

state変更後、後続の処理でstateの値を参照して処理したい

this.setState({
  hoge:'piyo';
});

fuga();//fugaの中でthis.state.hogeが参照される

気を付けていないと意外と書いてしまうかも知れません。

対応策

同期処理が必要な場合はstate経由は不適切なので、素直にfugaの引数として渡しましょう。

インクリメントなど前のstateに依存する処理

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

こんな感じの元のstateの値に依存する処理の場合、
連続で実行されると想定通りに動いてくれません。
例えば、 this.state.hoge=3の状態で連続して上記の処理を2回実行すると、
一回目は hoge: 3 + 1 と想定通りに動いてくれますが、
二回目までの間にthis.state.hogeが4に切り替わらないので、
二回目もhoge: 3 + 1 をsetStateの引数として渡してしまいます。
こうなるとReactは「 hoge:4が2回来たけど一回でいいな。」と考えてしまうので
hogeは5になりません。

対応策

functionをsetStateの引数として渡しましょう。

this.setState((state,prop) => {
  return {hoge:state.hoge + 1};
});

このようにstateとpropを引数に取ると、stateが切り替わってから関数を実行してくれるので、
前のstateに依存する処理を書いても正しくstateを変更できます。

stateの変更によってComponentが再描画されてから処理したい場合

setStateの第二引数にコールバック関数を渡しましょう。

まとめ

  • setStateしてもthis.stateはすぐには書き換わらない
  • 同期処理をしたい場合は素直に引数で
  • インクリメント系処理は関数をsetStateに渡す
  • 描画処理まで一通り終わってからの場合はコールバック関数
33
18
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?