Використання Actions у React 19 на практиці: для чого потрібні useActionState, use() та як працює компілятор.
React 19 actions дозволяють позбутися багато коду: обробників форм, оптимістичних оновлень, forwardRef та ручної мемоізації. Навіщо тоді useActionState, use() та зміни в компіляторі?
Джерела: React 19 Shipped Nine Months Ago. Most Teams Are Still Writing Code It Made Obsolete.
Багато команд підвищили номер версії React та залишили все інше без змін. Флаги завантаження, обробка помилок та оптимістичні оновлення, написані ними багато років тому, досі існують у кодбазі, оскільки оновлення ніколи їх не пошкодило. Воно лише зробило їх зайвими. Це огляд вручну написаного коду, який тепер автоматично обробляє React 19.
Патерн, який постійно зустрічається
Якщо відкрити майже будь-який компонент форми в проекті React 19, ви побачите однакову структуру. Існує три елементи стану: один для показу статусу завантаження, один для помилок та один для підтвердження успішності. Є асинхронний обробник надсилання даних, який викликає e.preventDefault(), увімкнює показ статусу завантаження, очищує попередні помилки, чекає на відповідь сервера, у try увімкнює показ статусу успіху, у catch копіює повідомлення у поле помилок та у finally вимикає показ статусу завантаження.
Цей підхід залишався стандартним з моменту популярності React та ефективно працює. У React 19 він також став зайвим – тепер один хук відповідає за обробку запитів у очікуванні, помилок та результатів, включаючи порядок виконання послідовних запитів. Більшість команд навіть не помітила цього, оскільки оновлення не вимагало змін.
Що є стабільним, а що ні
Спочатку коротка інформація, адже деякі статті описують функції як вже доступні, хоча це не так.
Доступно у стабільній версії React 19.x:
- Дії та хуки, побудовані на них:
useActionState,useFormStatusтаuseOptimistic. - API
use()для читання обіцянок та контексту під час відображення. refяк звичайний атрибут, що робитьforwardRefзастарілим.- Метадані оригінального документа: теги
<title>,<meta>та<link>, які генеруються з компонентів. - React Compiler, який досяг версії 1.0 у жовтні 2025 року та підтримує версії аж від React 17.
- Додатки з версії 19.2, такі як
<Activity>таuseEffectEvent.
На момент написання цього тексту компонент <ViewTransition> та Fragment Refs все ще є канарковими або експериментальними: вважайте будь-які елементи, які використовують їх, застарілими та перевіряйте примітки до версії, яку ви фактично встановлюєте.
Actions: нова модель для асинхронного стану
Основною ідеєю React 19 є Action — асинхронна функція, яка передається для виконання певних дій під час переходу стану. React бере на себе все, що пов’язано з цим процесом: обробку поточного стану, помилок, оптимістичні оновлення та скидання форм, усе те, що раніше команди мусили писати вручну.
useActionState, useFormStatus та useOptimistic — це не три незалежні функції. Це три різні способи представлення одного й того самого механізму.
useActionState замінює патерн з трьома флагами
Замість тріо „завантаження“, „помилка“ та „успіх“ ви пишете функцію Action, яка отримує попередній стан та дані форми та повертає наступний стан. Цю функцію разом із початковим станом ви передаєте у useActionState. Цей хук повертає три елементи: поточний стан, функцію для форми та булеве значення isPending.
Компонент потім виконує три прості дії. Атрибут action форми отримує безпосередньо повернуту функцію. Кнопка є недійсною, поки isPending дорівнює true. А будь-яке повідомлення читається з поверненого стану. Не існує стану завантаження, стану помилки, try, catch чи finally, preventDefault чи можливості ручного скидання.
Передача функції в action є навмисною. HTML-форми завжди мали атрибут action, і React 19 його відновив. Це дозволяє досягти поступового покращення функціоналу — форма може надсилати дані навіть без JavaScript, а React покращує її поведінку після завантаження скриптів.
useFormStatus дозволяє кнопці дізнаватися про свою форму
Найкраще використання useFormStatus — це кнопка надсилання, яку можна повторно використовувати. Усередині неї хук повертає прапорець pending, який описує батьківську форму, без передачі жодних параметрів. Кнопка сама себе вимикає та змінює свій текст на щось на кшталт „Зберігання“, поки форма знаходиться у стані очікування. Помістіть цей компонент будь-де всередині будь-якої форми — він просто буде працювати, що усуває необхідність передачі параметрів для дуже поширеної потреби. Є один недолік: хук читає статус форми, яка оточує компонент, тому його потрібно відображати всередині форми, а не поруч з нею.
useOptimistic дозволяє ефективно керувати миттєвою зворотною відповіддю
Оптимістичні оновлення відображають користувачеві очікуваний результат відразу, ще до підтвердження з боку сервера, та самостійно коригуються у разі невдачі запиту. Якщо це робити вручну, потрібні тимчасові ідентифікатори, окремий список завершених не повністю операцій, логіка об’єднання даних та код для скасування змін у відгалуженні на випадок помилки. Легко допустити приховані помилки.
За допомогою useOptimistic ви передаєте хуку справжній список разом із невеликим функціоналом, який описує, як додати елемент із позначкою «у процесі». У функції дії форми ви викликаєте функцію-встановлювач, яку вона повертає, а потім чекаєте на збереження даних. Інтерфейс відразу відображає новий елемент, можливо, з зниженою прозорістю поки він у процесі обробки. Коли дія завершується, справжні дані замінюють оптимістичну копію, а якщо збереження не вдалося, React самостійно повертається до попереднього стану. Не потрібні блоки обробки помилок чи ручне скасування змін.
use(): умовне завантаження ресурсів
use() — це новий API, який читає ресурс, такий як обіцянка або контекст, під час відображення. На відміну від усіх інших хуків, його можна викликати умовно. Компонент може отримати дані користувача, рано повернутися, якщо деталі приховані, а лише потім прочитати його налаштування. Обгорніть цю структуру в межі Suspense із запасним варіантом, і React призупинить відображення, поки не надійдуть дані.
Існує одна важлива обмеження: обіцянки, які передаються до use(), мають залишатися стабільними між різними відображеннями, тому їх слід створювати поза межами компонента або використовувати шар кешування, такий як React Query чи SWR, або навіть простий мапування на рівні модуля за ключем ID. Обіцянка, яка створюється заново при кожному відображенні, змушує запасний варіант залишатися на екрані вічно.
ref як проп
Ця зміна є простою. Тепер компоненти-функції отримують ref як звичайний проп, тож ви можете передавати його до базового елемента введення без необхідності обгортати компонент у forwardRef. Функціонування залишається ідентичним – лише менше кількість обгорток та імпортів. Існуючий код з forwardRef продовжуватиме працювати, оскільки відмова від нього відбувається поступово та без порушень, але нові компоненти не повинні ним користуватися.
Компілятор React
Компілятор – це найтихіше з усіх оновлень. Він аналізує компоненти під час збірки та застосовує мемоізацію, яку команди зазвичай або реалізують вручну, що може бути несумісним із useMemo, useCallback та React.memo, або ж повністю її ігнорують. Ви пишете звичайні компоненти, а компілятор правильно додає механізм кешування.
Щоб спробувати це, встановіть плагін Babel babel-plugin-react-compiler та додайте його до списку плагінів у вашій конфігурації Babel. Оскільки він також підтримує React 17 та 18, ви можете його використовувати, не оновлюючи спочатку React, що допомагає командам, які не можуть піднятися на нову версію, але хочуть отримати переваги щодо продуктивності.
Примітка щодо безпеки для серверних компонентів
У початку 2026 року попередження щодо безпеки, пов’язані з відмовою у обслуговуванні та витоком вихідного коду, вплинули на пакети react-server-dom-*; для кожної підтримуваної версії були опубліковані виправлені версії. Якщо ви використовуєте React Server Components, перевірте встановлену версію згідно з актуальними попередженнями та використовуйте виправлену версію або новішу. Не покладайтеся на пам’ять щодо того, яка версія є безпечною.
Що робити цього тижня
- Нові форми: від самого початку використовуйте
useActionState— визначте дію, передайте її до хука та прочитайте значенняisPendingз отриманих даних, не створюючи жодних власних флагів. - Існуючі обробники: не переписуйте все одразу. Виберіть один з них, перетворіть його на Action та подивіться, як це працює. Покращення читабельності зазвичай настільки очевидне, що дозволяє самостійно визначити пріоритет міграції.
- Компілятор: додайте його до налаштувань вашої сборки. Це незначна зміна, яка працює з існуючим кодом та не вимагає його переписування, що робить її найпростішим та найефективнішим способом оновлення до React 19.
- Компоненти серверу: перевірте свою версію щодо виправлень безпеки.
Заголовкові фічі привернули увагу під час випуску. Справжня зміна полягає у тому, що дії стали стандартною моделлю для будь-яких асинхронних змін стану, що тихо усуває значну частину коду, який розробники React пишуть щодня. Багато команд оновили свої системи, але код все ще чекає на переробку.