前回のReact 18への予習シリーズ:トランジションで予告したように、今回はConcurrent Mode(並列モード)の説明を行いたいと思います。
https://commons.wikimedia.org/wiki/File:Simultaneous.jpg より
JavaScriptはシングルスレッド
JavaScriptはシングルスレッドです。ただしJavaScriptはイベント駆動モデルなので、プログラムの途中に画面表示や通信等があれば、それらの処理が終わるのを待つのではなく、その時点で保留されているイベント等の処理に切り替かわります。 (画面表示や通信等の終了後に行う処理があればコールバック引数に指定しておきます)。
これにより、シングルスレッドでありながらユーザー(人間)には同時にいくつもの処理を行っているように見えます。
しかし、JavaScriptが大量の数値計算や複雑なデータ構造の変更処理などを開始すると マウス・クリック等のイベントには反応出来なくなり、ユーザーは待たされる印象を受けます。
仮想DOM(Virtual DOM)
さて、以下はReactの仮想DOM(Virtual DOM)の説明図です、ここでは仮想DOMの説明は省略しますが、知らない方はネットを検索してくさい。
仮想DOMの処理はメモリー上にDOM相当のデータ構造を構築し、その差分を取ったりする、比較的重い処理です。
React 15.xまでのReactは仮想DOMを含むレンダリング処理が始まると、終了するまではイベント等には反応しなくなります。このようなレンダリング処理はブロッキングレンダリングと呼ばれています。
React Fiber
React 16.0は仮想DOMを含むレンダリングエンジンがReact Fiberと呼ばれる(最近はFiberという言葉を聞かないので「呼ばれていた」かも?)新しいものに置き換えられました。
Fiberはレンダリング処理を細かい単位に分割しレンダリングを行います、そして1つの単位の処理が終わるとイベント処理や他のレンダリング処理に移れます。このようなレンダリング処理は中断可能(interruptible)なレンダリングと呼ばれています。
また、Fiberではレンダリングを中断したり、再開したりもできます。
- 現在のレンダリングを中断する
- 他の部分のレンダリングを開始し完了する
- 先ほど中断したレンダリングを再開する
ただし、React 16.0ではFiberの機能を使える公開APIはありませんでした、そしてReact 16.13でReact公式ドキュメント:並列モード API リファレンス(実験的機能)が導入されました。
これらのAPIはReact 17.0で正式リリースされると思われていたのですが、React v17.0はバグ修正に注力され並列モードAPIは正式リリースされませんでした。
そして、React 18.0で正式リリースされる事になりました。
Transition
前回のReact 18への予習シリーズ:トランジションで説明した、Transition(トランジション)ではFirst Page画面を表示中に、表示されていない仮想DOM上で通信処理とNext Page画面が作られていました。
- First Page画面はTransitionが始まった時点で画面は完成したように見えますが、
Next
ボタンがNext...
に変更されています - Next Pageの処理は通信が終わってから始まるのではなく、Transitionが始まった時点から見えない仮想DOM上の処理が始まっています
このように複数のレンダリング中断・再開できConcurrent Modeの機能でTransitionが実現されているのです。
DeferredValue
キーを入力するとその場で検索結果が表示されるような、インタラクティブな検索機能を15.xまでのReactで実現しようとすると、レンダリングの遅さからカクカクした動作になります。
さらにレンダリングが遅くなるために入力文字列の表示も遅れてしまいUXの悪いアプリになってしまいます。→ 実行例 並列的 UI パターン:素朴な実装サンプルコード
そこで、文字入力欄等は毎回レンダリングしつつ、遅い処理のレンダリングを遅延(スキップする)ための関数がDeferredValueです。→ 実行例 並列的 UI パターン:useDeferredValueサンプルコード
これもDeferredValueで指定された部分のみレンダリングを特別扱いできるConcurrent Modeの機能で実現されています。
まとめ
- バージョン15.xまでのReactはレンダリングが始まるとイベント等の反応が悪くなり、UX上の問題でした
- バージョン16でレンダリング・エンジンをReact Fiberと呼ばれる細かい単位で、中断・再開可能なエンジンに置き換えられ、Reactの提供する機能のUX改善が行われました
- バージョン16.13でFiberの機能をいかしたTransitionやDeferredValueなど実験的APIが公開されました
- バージョン18でTransitionやDeferredValueなどが正式なAPIになりました
- 今後のReactアプリでは、UX向上のためTransitionやSuspence、DeferredValueが盛んに使われるようになると思います
さらに知るには、React公式ドキュメントの並列モードの導入(実験的機能) を読み、並列的 UI パターンのコードを実行・読んでみると良いと思います。