Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Чому React тепер може переривати рендер?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)React може переривати рендер, тому що тепер він - **кооперативний планувальник**, а не лінійний виклик функцій. **Ключове:** це стало можливим завдяки Fiber-архітектурі (поділ роботи на дрібні кроки), Concurrent Rendering (пріоритети й асинхронність) і Scheduler API (поступка браузеру).Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 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-фазі.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.