v19.2Latest

UIをツリーとして理解する

あなたのReactアプリは、多くのコンポーネントが互いにネストされ、形を成してきています。Reactはどのようにしてアプリのコンポーネント構造を追跡しているのでしょうか?

Reactや他の多くのUIライブラリは、UIをツリーとしてモデル化します。アプリをツリーとして考えることは、コンポーネント間の関係を理解するのに役立ちます。この理解は、パフォーマンスや状態管理といった将来の概念をデバッグする際に役立つでしょう。

学習内容
  • Reactがコンポーネント構造をどのように「見る」か
  • レンダーツリーとは何か、そしてその有用性
  • モジュール依存ツリーとは何か、そしてその有用性

ツリーとしてのUI

ツリーはアイテム間の関係モデルです。UIはしばしばツリー構造を用いて表現されます。例えば、ブラウザはHTML(DOM)やCSS(CSSOM)をモデル化するためにツリー構造を使用します。モバイルプラットフォームも、ビューの階層を表現するためにツリーを使用します。

3つのセクションが水平方向に配置された図。最初のセクションには、垂直に積み重ねられた3つの長方形があり、それぞれに「Component A」、「Component B」、「Component C」というラベルが付いています。次のペインへ移行する矢印には、Reactのロゴと「React」というラベルがあります。中央のセクションにはコンポーネントのツリーがあり、ルートは「A」、2つの子は「B」と「C」とラベル付けされています。次のセクションへは、Reactのロゴと「React DOM」というラベルが付いた矢印で移行します。3番目で最後のセクションはブラウザのワイヤーフレームで、8つのノードからなるツリーが含まれており、そのうちの一部のみがハイライトされています(中央セクションからのサブツリーを示しています)。3つのセクションが水平方向に配置された図。最初のセクションには、垂直に積み重ねられた3つの長方形があり、それぞれに「Component A」、「Component B」、「Component C」というラベルが付いています。次のペインへ移行する矢印には、Reactのロゴと「React」というラベルがあります。中央のセクションにはコンポーネントのツリーがあり、ルートは「A」、2つの子は「B」と「C」とラベル付けされています。次のセクションへは、Reactのロゴと「React DOM」というラベルが付いた矢印で移行します。3番目で最後のセクションはブラウザのワイヤーフレームで、8つのノードからなるツリーが含まれており、そのうちの一部のみがハイライトされています(中央セクションからのサブツリーを示しています)。

ReactはあなたのコンポーネントからUIツリーを作成します。この例では、そのUIツリーがDOMへのレンダリングに使用されます。

ブラウザやモバイルプラットフォームと同様に、Reactもツリー構造を使用して、Reactアプリ内のコンポーネント間の関係を管理およびモデル化します。これらのツリーは、データがReactアプリをどのように流れるかを理解し、レンダリングやアプリのサイズを最適化するための有用なツールです。

レンダーツリー

コンポーネントの主な特徴の一つは、他のコンポーネントを組み合わせてコンポーネントを作成できる能力です。コンポーネントをネストする際には、親コンポーネントと子コンポーネントの概念が生まれ、各親コンポーネント自体が別のコンポーネントの子である可能性があります。

Reactアプリをレンダリングするとき、この関係をツリーでモデル化することができ、それはレンダーツリーとして知られています。

以下は、インスピレーションを与える名言をレンダリングするReactアプリです。

5つのノードを持つツリーグラフ。各ノードはコンポーネントを表します。ツリーのルートはAppで、そこから「InspirationGenerator」と「FancyText」へ向かう2本の矢印が伸びています。矢印には「renders」という単語がラベル付けされています。「InspirationGenerator」ノードも、「FancyText」と「Copyright」ノードを指す2本の矢印を持っています。5つのノードを持つツリーグラフ。各ノードはコンポーネントを表します。ツリーのルートはAppで、そこから「InspirationGenerator」と「FancyText」へ向かう2本の矢印が伸びています。矢印には「renders」という単語がラベル付けされています。「InspirationGenerator」ノードも、「FancyText」と「Copyright」ノードを指す2本の矢印を持っています。

Reactは、レンダリングされたコンポーネントで構成されるUIツリーであるレンダーツリーを作成します。

例のアプリから、上記のレンダーツリーを構築することができます。

ツリーはノードで構成され、各ノードはコンポーネントを表します。AppFancyTextCopyrightなどは、すべてツリー内のノードです。

Reactレンダーツリーのルートノードは、アプリのルートコンポーネントです。この場合、ルートコンポーネントはAppであり、Reactが最初にレンダリングするコンポーネントです。ツリー内の各矢印は、親コンポーネントから子コンポーネントを指しています。

Deep Dive
レンダーツリーにHTMLタグはどこにあるのか?

レンダーツリーは、Reactアプリケーションの単一のレンダーパスを表します。条件付きレンダリングでは、親コンポーネントは渡されたデータに応じて異なる子コンポーネントをレンダリングする可能性があります。

アプリを更新して、インスピレーションを与える引用文または色を条件付きでレンダリングすることができます。

6つのノードを持つツリーグラフ。ツリーの最上位ノードは「App」とラベル付けされており、2本の矢印が「InspirationGenerator」と「FancyText」とラベル付けされたノードに伸びています。矢印は実線で、「renders」という単語でラベル付けされています。「InspirationGenerator」ノードにはさらに3本の矢印があります。「FancyText」と「Color」ノードへの矢印は破線で、「renders?」とラベル付けされています。最後の矢印は「Copyright」とラベル付けされたノードを指しており、実線で「renders」とラベル付けされています。6つのノードを持つツリーグラフ。ツリーの最上位ノードは「App」とラベル付けされており、2本の矢印が「InspirationGenerator」と「FancyText」とラベル付けされたノードに伸びています。矢印は実線で、「renders」という単語でラベル付けされています。「InspirationGenerator」ノードにはさらに3本の矢印があります。「FancyText」と「Color」ノードへの矢印は破線で、「renders?」とラベル付けされています。最後の矢印は「Copyright」とラベル付けされたノードを指しており、実線で「renders」とラベル付けされています。

条件付きレンダリングでは、異なるレンダリング間で、レンダーツリーは異なるコンポーネントをレンダリングする可能性があります。

この例では、inspiration.typeの値に応じて、<FancyText>または<Color>をレンダリングする可能性があります。レンダーツリーはレンダーパスごとに異なる可能性があります。

レンダーツリーはレンダーパス間で異なる可能性がありますが、これらのツリーは一般的に、Reactアプリにおけるトップレベルコンポーネントとリーフコンポーネントを特定するのに役立ちます。トップレベルコンポーネントはルートコンポーネントに最も近いコンポーネントであり、その下にあるすべてのコンポーネントのレンダリングパフォーマンスに影響を与え、しばしば最も複雑さを含んでいます。リーフコンポーネントはツリーの下部近くにあり、子コンポーネントを持たず、しばしば頻繁に再レンダリングされます。

これらのカテゴリのコンポーネントを特定することは、アプリのデータフローとパフォーマンスを理解するのに役立ちます。

モジュール依存ツリー

Reactアプリにおけるもう一つの関係性で、ツリーでモデル化できるものは、アプリのモジュール依存関係です。コンポーネントやロジックを別々のファイルに分割すると、コンポーネント、関数、または定数をエクスポートするJSモジュールを作成します。

モジュール依存ツリーの各ノードはモジュールであり、各ブランチはそのモジュール内のimport文を表します。

前のInspirationsアプリを例にとると、モジュール依存ツリー、または略して依存ツリーを構築することができます。

7つのノードを持つツリーグラフ。各ノードにはモジュール名がラベル付けされている。ツリーの最上位ノードは'App.js'とラベル付けされている。'InspirationGenerator.js'、'FancyText.js'、'Copyright.js'のモジュールを指す3本の矢印があり、矢印には'imports'とラベル付けされている。'InspirationGenerator.js'ノードから、'FancyText.js'、'Color.js'、'inspirations.js'の3つのモジュールに伸びる3本の矢印がある。矢印には'imports'とラベル付けされている。7つのノードを持つツリーグラフ。各ノードにはモジュール名がラベル付けされている。ツリーの最上位ノードは'App.js'とラベル付けされている。'InspirationGenerator.js'、'FancyText.js'、'Copyright.js'のモジュールを指す3本の矢印があり、矢印には'imports'とラベル付けされている。'InspirationGenerator.js'ノードから、'FancyText.js'、'Color.js'、'inspirations.js'の3つのモジュールに伸びる3本の矢印がある。矢印には'imports'とラベル付けされている。

Inspirationsアプリのモジュール依存ツリー。

ツリーのルートノードはルートモジュールであり、エントリポイントファイルとも呼ばれます。多くの場合、ルートコンポーネントを含むモジュールです。

同じアプリのレンダーツリーと比較すると、類似した構造がありますが、いくつかの注目すべき違いがあります:

  • ツリーを構成するノードはコンポーネントではなく、モジュールを表します。
  • 非コンポーネントモジュール(例:inspirations.js)もこのツリーで表現されます。レンダーツリーはコンポーネントのみをカプセル化します。
  • Copyright.jsApp.jsの下に表示されますが、レンダーツリーでは、コンポーネントであるCopyrightInspirationGeneratorの子コンポーネントとして表示されます。これは、InspirationGeneratorがJSXをchildrenプロップとして受け取るため、Copyrightを子コンポーネントとしてレンダリングしますが、モジュールをインポートしないからです。

依存ツリーは、Reactアプリを実行するために必要なモジュールを決定するのに役立ちます。Reactアプリを本番用にビルドする際には、通常、クライアントに配信するために必要なすべてのJavaScriptをバンドルするビルドステップがあります。これを担当するツールはバンドラーと呼ばれ、バンドラーは依存ツリーを使用して含めるべきモジュールを決定します。

アプリが成長するにつれて、バンドルサイズも大きくなることがよくあります。大きなバンドルサイズは、クライアントがダウンロードして実行するのにコストがかかります。大きなバンドルサイズは、UIが描画されるまでの時間を遅らせる可能性があります。アプリの依存ツリーを把握することは、これらの問題のデバッグに役立つかもしれません。

まとめ

  • ツリーは、エンティティ間の関係を表現する一般的な方法です。UIをモデル化するためによく使用されます。
  • レンダーツリーは、単一のレンダリングにおけるReactコンポーネント間のネストされた関係を表します。
  • 条件付きレンダリングでは、レンダーツリーは異なるレンダリング間で変化する可能性があります。異なるプロップ値では、コンポーネントは異なる子コンポーネントをレンダリングする可能性があります。
  • レンダーツリーは、トップレベルコンポーネントとリーフコンポーネントを特定するのに役立ちます。トップレベルコンポーネントは、その下にあるすべてのコンポーネントのレンダリングパフォーマンスに影響を与え、リーフコンポーネントは頻繁に再レンダリングされることがよくあります。それらを特定することは、レンダリングパフォーマンスを理解しデバッグするのに有用です。
  • 依存ツリーは、Reactアプリ内のモジュール依存関係を表します。
  • 依存ツリーは、ビルドツールによってアプリを配信するために必要なコードをバンドルするために使用されます。
  • 依存ツリーは、ペイントまでの時間を遅くする大きなバンドルサイズのデバッグや、バンドルされるコードを最適化する機会を見つけるのに役立ちます。