Представление UI в виде дерева

Ваше приложение React формируется с множеством вложенных друг в друга компонентов. Как же React отслеживает структуру компонентов вашего приложения?

React, как и многие другие библиотеки, моделируют UI в виде дерева. Представив ваше приложении в виде дерева, вы сможете лучше понять взаимосвязь между компонентами, а так же это поможет вам в отладке будущих концепций, таких как: производительность и управление состоянием.

You will learn

  • Как 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'. 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'. 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, которое отображает вдохновляющие цитаты.

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 дерево состоящих из компонентов прошедших рендеринг.

Из примера приложения мы можем построить приведенное выше дерево рендеринга.

Дерево состоит из узлов, каждый из них представляет компонент. App, FancyText, Copyright и многие другие — это узлы нашего дерева.

Корневой узел в дереве рендеринга React является корневым компонентом приложения. В нашем случае корневой компонент предстовляет App и React рендерит его первым. Каждое ответление в дереве идет от родительского компонента к дочернему.

Deep Dive

Где же находятся HTML-теги в дереве рендеринга?

Возможно, вы уже заметили, что в приведенном выше дереве рендеринга нет упоминания о HTML-тегах, которые отображает каждый компонент. Это происходит потому, что дерево рендеринга состоит только из компонентов React.

Как фреймворк UI, React является платформо-независимым. Здесь же мы демонстрируем примеры рендеринга в web, где в качестве примитивов UI используется разметка HTML. Но приложение React так же может запускаться на мобильных или десктоп платформах, которые используют другие UI примитивы, такие как: UIView или FrameworkElement.

Но примитивы на этих платформах не являются частью 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'.

При условном рендеринге, в разных случаях, дерево рендеринга может строить разные компоненты.

В данном случае, мы рендерим <FancyText> или <Color> в зависимости от inspiration.type. При каждом рендеринге дерево может быть разным.

Хотя деревья рендеринга могут различаться в зависимости от этапа рендеринга, обычно они полезны для определения того, что представляют собой компоненты верхнего уровня и конечные компоненты в приложении React. Компоненты верхнего уровня — это те, которые находятся ближе к корневому компоненту. Они влияют на производительность рендеринга всех дочерних компонентов, и часто содержат наибольшую сложность. Конечные компоненты находятся в нижней части дерева. Они не имеют дочерних компонентов и часто рендерятся повторно.

Определение того, к какой категории относится компонент поможет вам лучше понять поток данных и улучшнить производительность вашего приложения.

Дерево зависимостей модулей

Еще одна связь в приложении React, которую можно смоделировать с помощью дерева, — это зависимости модулей приложения. Разбивая компоненты и логику на отдельные файлы, мы создаем JS-модули, в которые можно экспортировать компоненты, функции или константы.

Каждый узел в дереве зависимостей модулей является модулем, а каждую ветвь представляет import.

Если мы возьмем предыдущее приложение с вдохновляющими цитатами, мы сможем построить дерево зависимостей модулей.

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.js, также представлены в этом дереве. А дерево рендеринга инкапсулирует только компоненты.
  • Copyright.js появляется под App.js. Но в дереве рендеринга Copyright отображается как дочерний элемент InspirationGenerator. Это связано с тем, что Inspiration Generator принимает JSX в качестве дочерних пропсов, поэтому он отображает Copyright как дочерний компонент, но он не импортирует его.

Дерево зависимостей помогает определить какие модули необходимы для запуска вашего React приложения. При создании приложения для продакшена есть этап сборки, на котором весь необходимый JavaScript будет отправлен клиенту. На этом этапе сборщик пакетов использует дерево зависимостей для того, чтобы определить какие модули содержит проект.

По мере роста вашего приложения часто увеличивается и размер сборщика. При больших размерах требуются больше затрат для загрузки и запуска клиента, а так же это может задерживать прорисовку вашего UI. Понимание же дерева зависимостей вашего приложения может помочь в отладке и устранении этих проблем.

Recap

  • Деревья — это распространенный способ показать отношение между сущностями. Они очень частно используются для построения UI.
  • Деревья рендеринга представляют собой отношения между вложенными компонентами React в рамках одной отрисовки.
  • С отрисоквой по условию, дерево рендеринга может меняться при разных запусках. В зависимости от пропсов, компоненты могут отображать разные дочерние компоненты.
  • Деревья рендеринга помогают определить, что такое компоненты верхнего уровня и конечные компоненты. Компоненты верхнего уровня влияют на производительность отрисовки всех компонентов, находящихся под ними, а конечные компоненты часто перерисовываются повторно. Их выявление поможет вам для понимания и отладки производительности рендеринга.
  • Дерево зависимостей — это зависимость модулей в приложении React.
  • Деревья зависимостей пользуются инструментами сборки для объединения необходимого кода для отправки приложения.
  • Деревья зависимостей полезны для отладки пакетов больших размеров, которые замедляют прорисовку и предоставляют возможности для оптимизации.