Рендер і коміт
Перш ніж ваші компоненти відобразяться на екрані, їх повинен підготувати React. Розуміння кроків цього процесу допоможе осмислити те, як виконується код, і пояснити його логіку.
You will learn
- Що таке рендеринг у React
- Коли і чому React рендерить компонент
- Кроки виведення компоненту на екран
- Чому рендеринг не завжди призводить до оновлення DOM
Уявіть, що ваші компоненти — це кухарі на кухні, які створюють смачні страви з інгредієнтів. У такій історії React — це офіціант, який приймає від клієнтів замовлення та видає їм їжу. Цей процес замовлення та подачі UI складається з трьох кроків:
- Виклик рендеру (відправлення замовлення гостя на кухню)
- Рендеринг компонента (підготовка замовлення на кухні)
- Коміт у DOM (розміщення замовлення на столі гостя)
Illustrated by Rachel Lee Nabors
Крок 1: Запуск рендерингу
Існує дві причини для рендерингу компонента:
- Це початковий рендер компонента.
- Було оновлено стан компонента (або одного з його предків).
Початковий рендер
Під час запуску застосунку необхідно викликати початковий рендер. Фреймворки та пісочниці іноді приховують цей код, але це виконується через виклик createRoot
із передачею цільового вузла DOM, і потім через виклик методу render
із вашим компонентом:
import Image from './Image.js'; import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')) root.render(<Image />);
Спробуйте закоментувати виклик root.render()
— і побачите, що компонент зник!
Повторний рендер під час оновлення стану
Після першого рендерингу компонента ви можете викликати подальші рендеринги, оновивши його стан за допомогою функції set
. Оновлення стану вашого компонента автоматично додає рендеринг до черги. (Уявіть відвідувача ресторану, який після першого замовлення замовляє чай, десерт та всяку всячину залежно від стану спраги чи голоду).
Illustrated by Rachel Lee Nabors
Крок 2: React рендерить ваші компоненти
Коли викликано рендер, React викликає ваші компоненти, щоб з’ясувати, що виводити на екран. “Рендеринг” — це коли React викликає ваші компоненти.
- Під час початкового рендеру React викличе кореневий компонент.
- Для наступних рендерів React викликатиме компонент-функцію, оновлення стану якого власне почало рендер.
Цей процес є рекурсивним: якщо оновлений компонент повертає якийсь інший компонент, React буде рендерити цей компонент наступним, і якщо цей компонент також щось повертає, він буде рендерити той інший компонент наступним, і так далі. Процес триватиме доти, доки не залишиться більше вкладених компонентів, і React точно не знатиме, що саме має бути відображено на екрані.
У наступному прикладі React викличе Gallery()
й Image()
кілька разів:
export default function Gallery() { return ( <section> <h1>Скульптури, що надихають</h1> <Image /> <Image /> <Image /> </section> ); } function Image() { return ( <img src="https://i.imgur.com/ZF6s192.jpg" alt="'Рід квіткові' ('Floralis Genérica') — Едуардо Каталано (Eduardo Catalano): велетенська металева скульптура квітки зі світловідбивними пелюстками" /> ); }
- Під час початкового рендеру React створює вузли DOM для
<section>
,<h1>
і трьох тегів<img>
. - *Під час повторного рендеру React вираховує, які властивості елементів змінилися після попереднього рендеру та чи змінилися взагалі. Він нічого не робить з цією інформацією до наступного кроку, фази коміту.
Deep Dive
Стандартна поведінка, яка полягає у рендерингу всіх компонентів, вкладених в оновлений компонент, не є оптимальною для продуктивності, якщо оновлений компонент знаходиться дуже високо в дереві. Якщо ви зіткнулися з проблемою продуктивності, є кілька варіантів її вирішення, описаних в розділі “Продуктивність”. Не оптимізуйте передчасно!
Крок 3: React фіксує зміни в DOM
Після рендерингу (виклику) ваших компонентів React вносить зміни в DOM.
- Для початкового рендерингу React використовує API DOM
appendChild()
, щоб вивести на екран усі новостворені вузли DOM. - Для повторних рендерів React застосовує мінімально необхідні операції (обчислені під час рендерингу!), щоб оновити DOM відповідно до результату найсвіжішого рендерингу.
React змінює вузли DOM тільки якщо є різниця між рендерами. Наприклад, ось компонент, який повторно рендериться щосекунди з різними властивостями, що передаються від батьківського компонента. Зверніть увагу, що можна додати текст у <input>
, оновивши його value
, але текст не зникає, коли компонент рендериться наново:
export default function Clock({ time }) { return ( <> <h1>{time}</h1> <input /> </> ); }
Це працює, тому що на останньому кроці React оновлює лише вміст <h1>
новим time
. Він бачить, що <input>
з’являється в JSX в тому ж місці, що і минулого разу, тому React не чіпає <input>
— або його value
!
Епілог: Малювання браузера
Коли рендеринг завершено і React оновив DOM, браузер перемальовує екран. Хоча цей процес відомий як “рендеринг браузера”, ми будемо називати його “малюванням”, щоб уникнути плутанини в документації.
Illustrated by Rachel Lee Nabors