Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що відбувається на фазах render і commit і як React групує оновлення стану?

Оновлення екрана в React проходить три кроки:

  1. Тригер - перший рендер (root.render) або зміна стану (setState) компонента чи його предка;
  2. Рендер - React викликає функції компонентів, щоб дізнатися, що має бути на екрані. Для оновлень порівнює новий результат з попереднім (reconciliation) і визначає мінімальні зміни;
  3. Коміт - React застосовує зміни до DOM, потім браузер відмальовує екран і виконуються ефекти.

Важливі наслідки:

  • рендер - чисте обчислення. Його можна перервати, відкласти, виконати повторно або двічі (StrictMode). Тому в тілі компонента не можна мутувати зовнішні змінні, робити запити чи змінювати DOM - лише обчислювати JSX з props і стану;
  • рендер ≠ зміна DOM. Якщо результат рендеру той самий, DOM не чіпається. Зайві рендери коштують процесорного часу на обчислення, але не на роботу з DOM;
  • у конкурентному режимі рендер нетермінового оновлення (transition) можна перервати заради термінового (введення в поле), а коміт завжди синхронний і неподільний - користувач не бачить «половини» оновлення.

Групування оновлень (batching). Кілька setState в одному обробнику дають один рендер:

function handleClick() {
  setCount((c) => c + 1);
  setFlag((f) => !f);
  setItems([]);
  // один рендер після завершення обробника
}

З React 18 групування автоматичне скрізь: у таймерах, промісах, нативних обробниках подій. У React 17 і раніше воно працювало лише в обробниках подій React - setState у setTimeout давав окремий рендер на кожен виклик.

Черга оновлень. React обробляє оновлення по черзі: значення - замінює, функцію - викликає з результатом попереднього кроку:

setNumber(number + 5);      // замінити на 5
setNumber((n) => n + 1);    // 5 + 1
setNumber(42);              // замінити на 42
// результат 42

Коли потрібно оновити DOM негайно (виміряти щойно доданий елемент) - flushSync з react-dom. Це рідкісний виняток: він ламає групування й шкодить продуктивності.

Коли компонент перерендерюється: змінився його стан, перерендерився батько (навіть якщо props ті самі - якщо компонент не обгорнуто в memo і його не оптимізує React Compiler) або змінився контекст, який він читає.

Докладніше в документації: Рендер і коміт

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання