Skip to main content

Чому React тепер може переривати рендер?

1. Що було раніше (React ≤ 17)

  • Рендер був синхронним і блокуючим.
  • Коли викликався setState() -> React рекурсивно обходив усе піддерево і обчислював нове Virtual DOM.
  • Поки це відбувалося, JS-потік був повністю зайнятий - браузер не міг:
    • обробляти кліки чи скрол,
    • виконувати анімації,
    • реагувати на введення користувача.

Тобто рендер = одна довга "неперервана" операція.


2. Fiber - фундамент для переривного рендеру

З React 16 усе дерево компонентів зберігається у вигляді пов'язаних Fiber-вузлів. Кожен Fiber - це одиниця роботи (work unit), яка містить:

javascript
type FiberNode = { type: ComponentType; props: any; stateNode: any; child: FiberNode | null; sibling: FiberNode | null; return: FiberNode | null; lanes: PriorityBits; ... }

React може обробляти ці вузли по одному, а не все дерево за раз. Якщо між ними браузер каже:

"Гей, у мене подія від користувача!" React зупиняє обхід і поступається керуванням потоку.


3. Concurrent Rendering (React 18)

React перетворився на планувальник. Він стежить за пріоритетами різних завдань:

ПріоритетПрикладПоведінка
Високийклік, введення текстуВиконати одразу, перервавши поточний рендер
Середнійперехід (transition)Виконати, коли звільниться потік
Низькийфільтрація списку, підвантаження данихМожна робити "у фоні"

Коли надходить важливіша робота, React:

  1. зберігає контекст поточного Fiber-дерева;
  2. зупиняє поточний рендер (render phase);
  3. обробляє термінове оновлення;
  4. за потреби відновлює попередній рендер з того місця, де зупинився.

4. Що це дає

ДоПісля
Рендер блокує UIРендер можна призупинити
Усі оновлення рівніЄ пріоритети
Не можна скасувати рендерМожна скасувати і перерахувати
Ефекти викликаються один разЕфекти гарантовано викликаються тільки після commit-фази
Користувач чекаєUI лишається чутливим

5. Приклад інтуїтивно

javascript
startTransition(() => { setHeavyList(generateBigList()); // низькопріоритетне завдання });

Якщо в цей час користувач натисне кнопку або продовжить друкувати:

  • React ставить оновлення списку на паузу,
  • швидко обробляє клік (setState термінового типу),
  • потім відновлює фоновий рендер.

UI не зависає - тому що React вміє переривати й відкладати важкі оновлення.


6. Як це пов'язано з життєвим циклом

  • Render phase тепер може бути переривною і повторною. Компонент може "рендеритися" кілька разів, перш ніж потрапити в commit.
  • Commit phase залишається атомарною і синхронною - зміни в DOM застосовуються тільки коли React впевнений, що рендер завершено.
  • Ефекти (useEffect, useLayoutEffect) виконуються тільки після commit - тобто вже після всіх можливих скасувань і пауз.

7. Ключові технічні причини, чому React тепер може переривати рендер

  1. Fiber = одиниці роботи -> React може обробляти їх покроково.
  2. Scheduler API (cooperative scheduling) -> React знає, скільки часу минуло, і може поступатися потоком браузеру.
  3. Пріоритети (lanes) -> оновлення різних типів зберігаються в "доріжках" із різним пріоритетом.
  4. Concurrent Mode -> React не зобов'язаний одразу фіксувати зміни, він може відкладати їх.
  5. Suspense і Transitions -> дозволяють відкладати "важкі" рендери без блокування UI.

8. Візуально

javascript
Render phase (може бути призупинена) |-- Fiber A |-- Fiber B <- React може перервати тут | ^ користувач клікнув -> обробити термінове оновлення `-- Fiber C (доробити пізніше) Commit phase (завжди синхронна) `-- Застосувати зміни в DOM

9. Підсумок

React може переривати рендер, тому що тепер він - кооперативний планувальник, а не лінійний виклик функцій.

Це стало можливим завдяки:

  • Fiber architecture (поділ роботи на дрібні кроки),
  • Concurrent Rendering (пріоритети й асинхронність),
  • Scheduler API (поступка браузеру).

У підсумку:

  • UI завжди чутливий,
  • рендер можна призупиняти, скасовувати й відновлювати,
  • життєвий цикл став безпечнішим і точнішим у commit-фазі.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.