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

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

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

以下を学びます

  • Reactがコンポーネント構造を「認識」する方法
  • レンダリングツリーとは何か、何に役立つのか
  • モジュール依存関係ツリーとは何か、何に役立つのか

UIをツリーとして

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

Diagram with three sections arranged horizontally. In the first section, there are three rectangles stacked vertically, with labels 'Component A', 'Component B', and 'Component C'. Transitioning to the next pane is an arrow with the React logo on top labeled 'React'. The middle section contains a tree of components, with the root labeled 'A' and two children labeled 'B' and 'C'. The next section is again transitioned using an arrow with the React logo on top labeled 'React DOM'. The third and final section is a wireframe of a browser, containing a tree of 8 nodes, which has only a subset highlighted (indicating the subtree from the middle section).
Diagram with three sections arranged horizontally. In the first section, there are three rectangles stacked vertically, with labels 'Component A', 'Component B', and 'Component C'. Transitioning to the next pane is an arrow with the React logo on top labeled 'React'. The middle section contains a tree of components, with the root labeled 'A' and two children labeled 'B' and 'C'. The next section is again transitioned using an arrow with the React logo on top labeled 'React DOM'. The third and final section is a wireframe of a browser, containing a tree of 8 nodes, which has only a subset highlighted (indicating the subtree from the middle section).

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

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

レンダリングツリー

コンポーネントの主な機能は、他のコンポーネントのコンポーネントを構成できることです。コンポーネントをネストすると、親コンポーネントと子コンポーネントという概念が生まれ、各親コンポーネントは別のコンポーネントの子になる可能性があります。

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

インスピレーションを与える名言をレンダリングするReactアプリを次に示します。

import FancyText from './FancyText';
import InspirationGenerator from './InspirationGenerator';
import Copyright from './Copyright';

export default function App() {
  return (
    <>
      <FancyText title text="Get Inspired App" />
      <InspirationGenerator>
        <Copyright year={2004} />
      </InspirationGenerator>
    </>
  );
}

Tree graph with five nodes. Each node represents a component. The root of the tree is App, with two arrows extending from it to 'InspirationGenerator' and 'FancyText'. The arrows are labelled with the word 'renders'. 'InspirationGenerator' node also has two arrows pointing to nodes 'FancyText' and 'Copyright'.
Tree graph with five nodes. Each node represents a component. The root of the tree is App, with two arrows extending from it to 'InspirationGenerator' and 'FancyText'. The arrows are labelled with the word 'renders'. 'InspirationGenerator' node also has two arrows pointing to nodes 'FancyText' and 'Copyright'.

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

サンプルアプリから、上記のレンダリングツリーを構築できます。

ツリーはノードで構成され、各ノードはコンポーネントを表します。AppFancyTextCopyrightなどを始めとする全てがツリーのノードです。

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

深掘り

レンダリングツリーでは、HTMLタグはどこにあるのでしょうか?

上記のレンダリングツリーでは、各コンポーネントがレンダリングするHTMLタグについては言及されていません。これは、レンダリングツリーがReactのコンポーネントのみで構成されているためです。

Reactは、UIフレームワークとして、プラットフォームに依存しません。react.devでは、Webにレンダリングする例を紹介しており、UIのプリミティブとしてHTMLマークアップを使用しています。しかし、Reactアプリは、モバイルやデスクトッププラットフォームにレンダリングすることも可能で、その場合はUIViewFrameworkElementのような異なるUIプリミティブを使用する場合があります。

これらのプラットフォームのUIプリミティブは、Reactの一部ではありません。Reactのレンダリングツリーは、アプリがどのプラットフォームにレンダリングされるかに関わらず、Reactアプリに関する洞察を提供できます。

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

アプリを更新して、インスピレーションを与える引用句または色のいずれかを条件付きでレンダリングできます。

import FancyText from './FancyText';
import InspirationGenerator from './InspirationGenerator';
import Copyright from './Copyright';

export default function App() {
  return (
    <>
      <FancyText title text="Get Inspired App" />
      <InspirationGenerator>
        <Copyright year={2004} />
      </InspirationGenerator>
    </>
  );
}

Tree graph with six nodes. The top node of the tree is labelled 'App' with two arrows extending to nodes labelled 'InspirationGenerator' and 'FancyText'. The arrows are solid lines and are labelled with the word 'renders'. 'InspirationGenerator' node also has three arrows. The arrows to nodes 'FancyText' and 'Color' are dashed and labelled with 'renders?'. The last arrow points to the node labelled 'Copyright' and is solid and labelled with 'renders'.
Tree graph with six nodes. The top node of the tree is labelled 'App' with two arrows extending to nodes labelled 'InspirationGenerator' and 'FancyText'. The arrows are solid lines and are labelled with the word 'renders'. 'InspirationGenerator' node also has three arrows. The arrows to nodes 'FancyText' and 'Color' are dashed and labelled with 'renders?'. The last arrow points to the node labelled 'Copyright' and is solid and labelled with 'renders'.

条件付きレンダリングでは、異なるレンダリングにわたって、レンダリングツリーが異なるコンポーネントをレンダリングする場合があります。

この例では、inspiration.typeが何であるかによって、<FancyText>または<Color>をレンダリングする場合があります。レンダリングツリーは、各レンダリングパスで異なる場合があります。

レンダリングツリーはレンダリングパス間で異なる場合がありますが、これらのツリーは一般的にReactアプリのトップレベルおよびリーフコンポーネントが何であるかを識別するのに役立ちます。トップレベルコンポーネントは、ルートコンポーネントに最も近く、その下のすべてのコンポーネントのレンダリングパフォーマンスに影響を与え、多くの場合最も複雑な処理を含んでいます。リーフコンポーネントはツリーの下部に近く、子コンポーネントを持たず、頻繁に再レンダリングされます。

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

モジュール依存関係ツリー

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

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

前のInspirationsアプリを使用すると、モジュール依存関係ツリー、または略して依存関係ツリーを構築できます。

A tree graph with seven nodes. Each node is labelled with a module name. The top level node of the tree is labelled 'App.js'. There are three arrows pointing to the modules 'InspirationGenerator.js', 'FancyText.js' and 'Copyright.js' and the arrows are labelled with 'imports'. From the 'InspirationGenerator.js' node, there are three arrows that extend to three modules: 'FancyText.js', 'Color.js', and 'inspirations.js'. The arrows are labelled with 'imports'.
A tree graph with seven nodes. Each node is labelled with a module name. The top level node of the tree is labelled 'App.js'. There are three arrows pointing to the modules 'InspirationGenerator.js', 'FancyText.js' and 'Copyright.js' and the arrows are labelled with 'imports'. From the 'InspirationGenerator.js' node, there are three arrows that extend to three modules: 'FancyText.js', 'Color.js', and 'inspirations.js'. The arrows are labelled with 'imports'.

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

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

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

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

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

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

まとめ

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