執筆動機
- 実業務でReactを使用した開発を行っているが、詳細なReact内部での挙動について理解できていないため、調べて理解しようという試み
- n番煎じの記事となってしまいそうですが、自己理解のために書きます🐤
調べる前段階の理解
- ReactはSPA開発に適しているフレームワークであり、MPAとは異なりJavaScriptの挙動によって一部のHTML要素(コンポーネントとして指定した範囲)のみ更新をかけることができる
- これにより、画面コンポーネントの要素の再構築の負荷を下げることができる
- また、一部分のみ編集・更新対象として他のHTML要素に影響を及ぼさないため、例えば音楽を断続的に流しながらであったりなどの画面上での連続性を維持したままの実装が可能
- 実画面に反映している実際のHTMLとは別に、React上に仮想DOMという実画面のHTMLをコピーしたDOMを作成しておき、作成した仮想DOMに対して要素の編集操作を加える、という認識
- この仮想DOMをまず編集したのちに実際のDOMに変更反映をさせる、という点までは理解できている
- この過程のどこかで実際のDOMと仮想DOMの間での差分検出を行っているはず
- 多分仮想DOMをいじる前に差分検出を行っていると思うのだけど、自信がない
- この過程のどこかで実際のDOMと仮想DOMの間での差分検出を行っているはず
- 仮想DOMから実際のDOMに反映させるプロセスを「リコンシエーション」と呼ぶことも知っている
- ただ、具体的にReactフレームワーク内部でどのようにリコンシエーションが行われているのか人に説明できるレベルでは理解できていない
- 昔キャッチアップする際に調べた気がしたが、忘れてしまった👼
- この仮想DOMをまず編集したのちに実際のDOMに変更反映をさせる、という点までは理解できている
▶ここまで、ChatGPTに聞いたところ「概略理解はかなり正確です!」とのFBがもらえたので方向性は悪くなさそう
記事の想定読者
- つらつらと書いた「調べる前段階の理解」と同じくらいには理解できている気がする、という方
- Reactのリコンシエーションについてざっくり理解したい方
Reactの基礎文法を調べ直す
JSXとは?
- JSX = "JavaScript XML"の略
- Reactを実装するためのJavaScriptの拡張構文
- JavaScriptのシンタックスシュガーに過ぎない
- JavaScriptの構文だが、見た目はHTMLライク
- コンポーネントを書く手段はほかにも存在するが、JSXの簡潔さから、ほとんどのコードベースではJSXが使われている
要は、ReactはHTMLではなく、「HTMLのように見える要素」が、実際にはJavaScriptオブジェクトとして表現されているだけ。このため、画面の特定のコンポーネントをJavaScriptによって書き換えることができる。
Reactの根底にある思想
- ReactのElementは単なるJavaScriptのオブジェクトである
- この仕組みにより、UIを効率的に再描画できる
- 仮想DOMと差分検出アルゴリズムを活用し、最小限のDOM操作で高いパフォーマンスを実現したい
差分検出処理と差分アルゴリズム
差分検出処理 = Reconciliation
- Reactには、実際のDOMと仮想DOMとの間にある差分をより少ない計算量で検出できる強みがある
- これを 差分アルゴリズム という
差分アルゴリズム
- ルート要素の型に応じて、差分検出のアルゴリズムの挙動は異なる
- 実DOMと仮想DOMのDOM要素が異なる型(ex.
<a>
→<img>
) の時- ツリーを全て破棄して再構築
- 実DOMと仮想DOMのDOM要素が同じ型の時
- 変更された属性のみを更新 (ex.
className
のみ)
- 変更された属性のみを更新 (ex.
- 子ノードの要素追加など
-
key
を指定することで、Reactに変更箇所を一意に伝えることができ、計算量削減に役立つ
-
- 実DOMと仮想DOMのDOM要素が異なる型(ex.
仮想DOMの役割
- 基本的にアルゴリズムの木の最上部から再帰的に最下部まで移動することによって、JavaScriptで仮想DOMを生成
- ここで生成された仮想DOMを、Reactはメモリ内に保持しておく仕組みがある
- 差分検出アルゴリズムが仮想DOMを比較し、最小限の操作で実際のDOMを更新
まとめ
多分仮想DOMをいじる前に差分検出を行っていると思うのだけど、自信がない
- あっている
- そのために差分アルゴリズムを用いている
- 具体的な中身については宿題
具体的にReactフレームワーク内部でどのようにリコンシエーションが行われているのか人に説明できるレベルでは理解できていない
- ルート要素の型に応じて、差分検出のアルゴリズムが動作している
- ルート要素によってDOMをどのように操作するかは異なる
- 確実に言えることは、全ツリーを再描画せず最小限の変更点で済ませられるようにアルゴリズムが組まれている
次回以降への宿題
ひとりアドカレなので、自分への宿題とします。
- 今回は力尽きてしまったのですが、多分別途React Fiberについて調べたほうが理解が深まる
- React18に実装されている仕様らしく、飛ばさず理解したほうが良いにおいがする
- 差分アルゴリズムについても、別途理解したい
🔗参考Link
- JSX でマークアップを記述する
- Babel を使った JSX のトランスパイルを理解したメモ
- React 差分検出処理
- 調停(Reconciliation)
- 図で分かるReact18のしくみ
- React Fiberとその周りについて調べた
- React Fiberとは
- ReactはなぜFiberで書き直されたのか?Reactの課題と将来像を探る
- React は実際にどのように機能するのでしょうか? React.js の詳細 #1 (English)
余談
はじめてのひとりアドカレ2024 by hayami Advent Calendar 2024 8日目の記事です。キエーという気持ちになってきました。
アドベントカレンダー一覧の他のひとりアドカレに参加されている方の進捗を見ては、同じくコツコツひとりで書かれている方に「一緒に頑張ろう…!」と心の中でエールを送る毎日です。