← Усі статті

React 19: concurrent rendering, Actions і Suspense у продакшені

Розбір concurrent rendering у React 19: термінові та фонові оновлення, useTransition, useOptimistic і межі Suspense без блокування UI.

Зміст

Коротко

На Dev.to — глибокий розбір concurrent rendering у React 19: як розділити термінові оновлення (ввід, кліки) і фонові (фільтрація, мутації), щоб інтерфейс не «замерзав» на сотні мілісекунд. Ключові примітиви — Actions, useTransition, useOptimistic і координований Suspense.

Що сталося

Автор починає з типової помилки: кожен мережевий виклик обгортають у блокуючий loading, UI замирає при мутаціях, пошук «стрибає» на великих списках. React 19 вирішує це пріоритетами: фреймворк може переривати, відкладати й відновлювати роботу рендера.

Архітектура вводить дві «смуги» оновлень:

  • Термінові — натискання клавіш, клік; комітяться одразу.
  • Перехідні — важка фільтрація, розрахунки; поступаються терміновим.

useTransition повертає [isPending, startTransition]: обгортка state-update позначає його як нетермінове, isPending — для локального індикатора без блокування сторінки. Якщо користувач друкує швидше, ніж завершується фільтрація, React відкидає застарілий перехід і стартує новий — без ручного debounce і скасування запитів.

useOptimistic формалізує оптимістичний UI: показуємо intended result до відповіді сервера, при помилці React відкочує. Для чатів і форм це знімає ручну синхронізацію rollback.

Suspense у React 19 координує кілька async-меж: прогресивні fallback замість одного спінера на всю сторінку, один фінальний commit без миготіння.

Чому це важливо

Користувач відчуває відгуковість у мілісекундах. Пошук по 5–10k рядків, який лагає на кожен символ, «ламає» довіру до продукту. Concurrent-модель переносить складність пріоритетів у фреймворк — менше boolean isLoading і ланцюжків setState в обробниках.

Міграція покрокова: профілювати React DevTools, обгорнути дорогі updates у startTransition, додати межі Suspense навколо незалежних async-секцій. Автор вказує на 40–60% зниження блокуючого часу на важких UI при помірному зростанні пам'яті на tracking переходів.

На практиці

  1. Пошук/фільтриsetQuery синхронно, фільтр усередині startTransition; isPending для dim/spinner.
  2. Форми й чатuseOptimistic + server action у transition; rollback при помилці автоматично.
  3. Дані — вкладені Suspense по незалежних секціях, не одна boundary на весь layout.
  4. Поріг — transition має сенс для операцій >100 ms; миттєві updates лише додають overhead.

Підсумок

React 19 concurrent — не «ще один hook», а зміна моделі: пріоритет взаємодії користувача над фоновою роботою. Почати варто з пошуку та важких списків — там виграш видно одразу, без переписування всього застосунку.