Розуміння вашого UI як дерева
React-застосунок формується великою кількістю компонентів, які вкладені один в одного. Як React відстежує структуру компонентів у вашому застосунку?
Інтерфейс користувача (далі — UI) моделюється у вигляді дерева у React і багатьох інших UI-бібліотеках. Думати про ваш застосунок як про дерево — корисно, щоб розуміти зв’язки між компонентами. Це розуміння допоможе вам далі у налагодженні певних моментів як продуктивність та управління станом.
You will learn
- Як React “бачить” структури компонентів
- Що таке дерево рендерингу і чим воно корисне
- Що таке дерево залежностей модулів і чим воно корисне
Ваш UI у вигляді дерева
Дерева є моделлю зв’язків між елементами, і UI часто представлений за допомогою деревоподібних структур. Наприклад, браузери використовують деревоподібні структури для моделювання HTML (DOM) та CSS (CSSOM). Мобільні платформи також використовують дерева для представлення своєї ієрархії “екранів”.
![Діаграма із трьох секцій, розташованих горизонтально. У першій секції розташовані вертикально три прямокутники з написами 'Component A', 'Component B' та 'Component C'. Перехід до наступної секції здійснюється за допомогою стрілки з логотипом React над нею та підписом 'React'. Середня секція містить дерево компонентів: корінь, підписаний як 'A', і його двоє дітей, підписані як 'B' і 'C'. Перехід до наступної секції також здійснюється за допомогою стрілки з логотипом React над нею та підписом 'React DOM'. Третя і остання секція — це ескіз браузера, що містить дерево з 8 вузлами, в якому виділено кольором лише піддерево (що вказує на піддерево з середнього розділу).](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fpreserving_state_dom_tree.dark.png&w=1920&q=75)
![Діаграма із трьох секцій, розташованих горизонтально. У першій секції розташовані вертикально три прямокутники з написами 'Component A', 'Component B' та 'Component C'. Перехід до наступної секції здійснюється за допомогою стрілки з логотипом React над нею та підписом 'React'. Середня секція містить дерево компонентів: корінь, підписаний як 'A', і його двоє дітей, підписані як 'B' і 'C'. Перехід до наступної секції також здійснюється за допомогою стрілки з логотипом React над нею та підписом 'React DOM'. Третя і остання секція — це ескіз браузера, що містить дерево з 8 вузлами, в якому виділено кольором лише піддерево (що вказує на піддерево з середнього розділу).](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fpreserving_state_dom_tree.png&w=1920&q=75)
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="Застосунок 'Натхнення'" /> <InspirationGenerator> <Copyright year={2004} /> </InspirationGenerator> </> ); }
![Граф дерева з п'ятьма вузлами. Кожен вузол відповідає компоненту. Корінь дерева — це App, він має дві стрілки, які ведуть до 'InspirationGenerator' та 'FancyText'. Стрілки позначені словом 'renders'. Вузол 'InspirationGenerator' також має дві стрілки, що вказують на вузли 'FancyText' та 'Copyright'.](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Frender_tree.dark.png&w=1080&q=75)
![Граф дерева з п'ятьма вузлами. Кожен вузол відповідає компоненту. Корінь дерева — це App, він має дві стрілки, які ведуть до 'InspirationGenerator' та 'FancyText'. Стрілки позначені словом 'renders'. Вузол 'InspirationGenerator' також має дві стрілки, що вказують на вузли 'FancyText' та 'Copyright'.](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Frender_tree.png&w=1080&q=75)
React створює дерево рендерингу — дерево UI, складене з відрендерених компонентів.
З прикладу застосунку ми можемо побудувати вищеописане дерево рендерингу.
Дерево складається з вузлів, кожен з яких відповідає певному компоненту. App
, FancyText
, Copyright
— це приклади кількох вузлів у нашому дереві.
Кореневий вузол у дереві рендерингу React — це кореневий компонент застосунку. У цьому прикладі кореневим компонентом є App
, і це перший компонент, який React рендерить. Кожна стрілка у дереві напрямлена від батьківського до дочірнього компонента.
Deep Dive
У наведеному вище дереві рендерингу не згадуються HTML-теги, які кожен компонент рендерить. Це тому, що дерево рендерингу складається лише з компонентів React.
React як UI-фреймворк є платформонезалежним. На сайті uk.react.dev ми демонструємо приклади, які рендеряться для вебу, що використовує HTML-розмітку як свої UI-примітиви. Але React-застосунок може так само рендеритися для мобільної або стаціонарної платформи, що може використовувати інші UI-примітиви, як-от UIView або FrameworkElement.
Ці платформові 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="Застосунок 'Натхнення'" /> <InspirationGenerator> <Copyright year={2004} /> </InspirationGenerator> </> ); }
![Граф дерева із шістьма вузлами. Кореневий вузол дерева позначений як 'App' і має дві стрілки, що ведуть до вузлів, позначених як 'InspirationGenerator' та 'FancyText'. Стрілки мають тверді лінії і позначені словом 'renders'. Вузол 'InspirationGenerator' також має три стрілки. Стрілки до вузлів 'FancyText' і 'Color' пунктирні і позначені як 'renders?'. Остання стрілка вказує на вузол, позначений як 'Copyright', і є твердою та позначена словом 'renders'.](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fconditional_render_tree.dark.png&w=1200&q=75)
![Граф дерева із шістьма вузлами. Кореневий вузол дерева позначений як 'App' і має дві стрілки, що ведуть до вузлів, позначених як 'InspirationGenerator' та 'FancyText'. Стрілки мають тверді лінії і позначені словом 'renders'. Вузол 'InspirationGenerator' також має три стрілки. Стрілки до вузлів 'FancyText' і 'Color' пунктирні і позначені як 'renders?'. Остання стрілка вказує на вузол, позначений як 'Copyright', і є твердою та позначена словом 'renders'.](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fconditional_render_tree.png&w=1200&q=75)
За допомогою умовного рендерингу, посеред різних рендерів, дерево рендерингу може рендерити різні компоненти.
У цьому прикладі залежно від того, що є inspiration.type
, ми можемо відрендерити або <FancyText>
, або <Color>
. Дерево рендерингу може бути різним для кожного проходу рендеру.
Хоча дерева рендерингу можуть відрізнятися між різними проходами рендеру, вони загалом корисні для ідентифікації внутрішніх (top-level) та зовнішніх (leaf) компонентів у React-застосунку. Внутрішні компоненти — це компоненти, ближчі до кореневого компонента, які впливають на продуктивність рендерингу всіх компонентів під ними і часто є найбільш складними. Зовнішні компоненти, або листи, знаходяться в нижній частині дерева і не мають дочірніх компонентів та часто піддаються повторному рендерингу.
Ідентифікація цих категорій компонентів корисна для розуміння потоку даних (data flow) та продуктивності вашого застосунку.
Дерево залежностей модуля
Ще одним типом зв’язків у React-застосунку, що можуть бути змодельовані за допомогою дерева, є залежності модулів застосунку. Коли ми виносимо наші компоненти та логіку в окремі файли, ми створюємо JS-модулі, з яких можна експортувати компоненти, функції або константи.
Кожен вузол у дереві залежностей модулів — це модуль, а кожна гілка відповідає оператору import
у цьому модулі.
Якщо ми візьмемо попередній застосунок “Натхнення”, ми можемо побудувати дерево залежностей модулів, або скорочено — дерево залежностей.
![Граф дерева із сімома вузлами. Кожен вузол позначений назвою модуля. Кореневий вузол дерева позначений як 'App.js'. Від нього виходять три стрілки до модулів 'InspirationGenerator.js', 'FancyText.js' та 'Copyright.js', і ці стрілки позначені словом 'imports'. Від вузла 'InspirationGenerator.js' відходять три стрілки до трьох модулів: 'FancyText.js', 'Color.js' та 'inspirations.js'. Ці стрілки позначені словом 'imports'.](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fmodule_dependency_tree.dark.png&w=1920&q=75)
![Граф дерева із сімома вузлами. Кожен вузол позначений назвою модуля. Кореневий вузол дерева позначений як 'App.js'. Від нього виходять три стрілки до модулів 'InspirationGenerator.js', 'FancyText.js' та 'Copyright.js', і ці стрілки позначені словом 'imports'. Від вузла 'InspirationGenerator.js' відходять три стрілки до трьох модулів: 'FancyText.js', 'Color.js' та 'inspirations.js'. Ці стрілки позначені словом 'imports'.](/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fmodule_dependency_tree.png&w=1920&q=75)
Дерево залежностей модулів для застосунку “Натхнення”.
Кореневий вузол дерева — це кореневий модуль, відомий також як файл точки входу. Зазвичай це модуль, який містить кореневий компонент.
Порівнюючи з деревом рендерингу цього ж застосунку, бачимо схожі структури з деякими ключовими відмінностями:
- Вузли, які утворюють дерево, відповідають модулям, а не компонентам.
- Модулі, що не містять компонентів, як-от
inspirations.js
, також є у цьому дереві. Дерево рендерингу охоплює лише компоненти. Copyright.js
розташований безпосередньо підApp.js
, але в дереві рендерингу компонентCopyright
з’являється як дочірній елементInspirationGenerator
. Це тому, щоInspirationGenerator
приймає JSX як проп children, тому він рендеритьCopyright
як дочірній компонент, а не імпортує модуль.
Дерева залежностей корисні для визначення, які модулі необхідні для запуску вашого React-застосунку. Під час побудови готового до впровадження React-застосунку зазвичай є етап, який запакує (bundle) весь необхідний JavaScript-код для доставлення клієнту. Інструмент, що за це відповідає, називається бандлер, і бандлери використовують дерево залежностей для визначення, які модулі повинно бути включено.
Відповідно до того, як зростає ваш застосунок, збільшується і розмір запакованого застосунку — бандлу. Великі розміри бандлів є “дорогими” для завантаження та виконання клієнтом. Великі розміри бандлів можуть затримувати час відображення вашого UI. Розуміння дерева залежностей вашого застосунку може допомогти з налагодженням цих проблем.
Recap
- Дерева — це поширений спосіб представлення зв’язків між сутностями. Часто вони використовуються для моделювання UI.
- Дерева рендерингу відображають вкладені зв’язки між компонентами React у межах одного рендеру.
- З умовним рендерингом дерево рендерингу може змінюватися між різними рендерами. Залежно від різних значень пропсів компоненти можуть рендерити різні дочірні компоненти.
- Дерева рендерингу допомагають ідентифікувати, які компоненти є внутрішніми, а які — зовнішніми (листи). Внутрішні компоненти впливають на продуктивність рендерингу всіх компонентів-нащадків, а компоненти-листи часто піддаються повторному рендерингу. Їх ідентифікація корисна для розуміння та налагодження продуктивності рендерингу.
- Дерева залежностей відображають залежності модулів у React-застосунку.
- Дерева залежностей використовуються бандлерами, щоб запакувати необхідний код для доставлення застосунку.
- Дерева залежностей корисні для налагодження великих розмірів бандлів, які збільшують час до появи першого вмісту та показують можливі оптимізації відносно того, який код додається до бандлу.