React学習5日目:バッチ処理と関数型アップデート

ステートセッターを複数回呼び出すと、レンダリングも複数回発生すると思っていました。

私の勘違いでした。

Reactはもっと賢いです。「Automatic Batching(自動バッチ処理)」と呼ばれるプロセスを使用しています。

更新のたびにレンダリングするのではなく、Reactはそれらをグループ化します。すべての更新をまとめて、一度のレンダリングで実行します。これによりパフォーマンスが向上します。

今日学んだことは以下の通りです。

バッチ処理のプロセス

複数のステート関数を呼び出すと、Reactは以下のフローに従います。

  • 複数のステート更新が発生する。
  • Reactがそれらをまとめてバッチ処理する。
  • Reactが一度だけレンダリングを実行する。
  • ReactがUIに変更をコミットする。

標準的なアップデートの問題点

次のようなコードを試してみました。 setCount(count + 1); setCount(count + 1); setCount(count + 1);

カウントが0から3になると予想していましたが、実際には0から1になりました。

これは、setCount(count + 1) が「カウントを増やす」という意味ではなく、「カウントをこの特定の値に設定する」という意味だからです。

もし count が0であれば、すべての行がReactに対して「カウントを1に設定せよ」と指示していることになります。Reactはこれらをバッチ処理し、最終的な指示が「カウントを1に設定する」であると判断します。

解決策:関数型アップデート

これを解決するには、関数型アップデートを使用する必要があります。これを使うと、アップデートキューにある最新のステートを利用できます。

正しい方法: setCount((prev) => prev + 1);

このパターンを使用すると、Reactは各アップデートに最新の値を与えます。

  • 最初のアップデート: 0 + 1 = 1
  • 2番目のアップデート: 1 + 1 = 2
  • 3番目のアップデート: 2 + 1 = 3

これで、カウンターは実際に3に到達します。

よくある間違い

以前、このように書いてしまいました。 setCount((prev) => { prev + 1 });

カウンターが undefined になってしまいました。 アロー関数で波括弧 {} を使用する場合は、return キーワードを使用する必要があります。 代わりにこちらを使用してください: setCount((prev) => prev + 1);

まとめ:

  • Reactは速度向上のために複数のステート更新をバッチ処理する。
  • setState の呼び出しが常に即座にレンダリングをトリガーするわけではない。
  • 標準的なアップデートは、現在のレンダリングサイクルの値を使用する。
  • 関数型アップデートは、アップデートキュー内の最新のステートを使用する。
  • Reactはこれらの変更を管理するために、内部の Update Queue(アップデートキュー)を使用する。

出典: https://dev.to/bismay-exe/day-5-of-learning-react-understanding-automatic-batching-functional-updates-397k