React 19, стабільний з грудня 2024, - найзначніша зміна API surface з часу введення Hooks у 16.8. Реліз вводить п'ять нових примітивів, що разом переключають mutation model React від component-external store патерну (Redux, useState + useEffect + fetch) до action-based моделі, обізнаної про сервер, сумісної з Progressive Enhancement і тісно інтегрованої з concurrent renderer. У цій статті розбираю кожен примітив на рівні механізму - як він працює зсередини і коли застосовувати.
Частина I - useOptimistic та use(): механізми
- useOptimistic:
const [optimisticState, addOptimistic] = useOptimistic(state, updateFn). При викликуaddOptimistic(value)React застосовуєupdateFn(currentState, value)під час рендерингу для обчислення оптимістичного стану. При помилці action - автоматичний rollback доstateдо викликуaddOptimistic. Кілька конкурентних оптимістичних оновлень застосовуються по порядку з незалежною обробкою помилок. - use(promise) - Suspense-інтеграція у Client Components:
const data = use(promise). Якщо Promise pending - React призупиняє компонент. На відміну відuseEffect + useState, немає проміжного рендерингу зnull. Server Component ініціює fetch (не await-ить), передає Promise у Client Component; Client Component викликаєuse(promise). - use(context) - умовний доступ до Context: Може бути викликаний усередині conditional-блоків - неможливо з
useContext.if (isAdmin) { const config = use(AdminContext); }- тепер валідний патерн.
Частина II - Server Actions та useActionState
- Server Actions - механізм: Next.js присвоює кожній
'use server'-функції унікальний action ID. Клієнт відправляє HTTP POST з action ID; сервер виконує функцію. CSRF-захист вбудований автоматично. Progressive Enhancement:<form action={serverAction}>працює без JavaScript. - Безпека: Аргументи Server Action - контрольовані користувачем дані HTTP POST. Завжди валідувати server-side:
const user = await getSession(); if (item.userId !== user.id) throw new Error('Unauthorized'); - useActionState (перейменований з useFormState):
const [state, dispatch, isPending] = useActionState(action, initialState). Action:(previousState, formData) => Promise<newState>.isPending: trueпоки action виконується. ЗамінюєuseState + setLoadingпатерн. - useFormStatus:
const { pending } = useFormStatus(). Читає статус найближчої батьківської<form>. Має викликатися у компоненті-нащадку форми.<SubmitButton>патерн без prop drilling.
Частина III - Синтаксичні зміни та Action-based архітектура
- ref як prop (forwardRef застарів):
function Input({ ref, ...props }) { return <input ref={ref} {...props} />; }безforwardRef. - Context як provider:
<ThemeContext value={theme}>замість<ThemeContext.Provider value={theme}>. - Повна компоновка mutation патерну: (1) Server Action; (2)
useActionState- persistent state +isPending; (3)useOptimistic- миттєвий UI-відгук; (4)useFormStatusу<SubmitButton>. Ці чотири примітиви замінюють Zustand store зloading + error + optimistic+fetchуuseEffect+try/catchrollback. - PPR + useOptimistic: PPR обслуговує статичний shell з CDN; dynamic holes - інтерактивні острівці з
useOptimistic. Детальніше - у гайді з PPR. - Приклад Add to Cart (headless Shopify):
const [cart, addToCart, isPending] = useActionState(addToCartAction, initial); const [optimisticCart, addOptimistic] = useOptimistic(cart, (s, line) => ({ ...s, lines: [...s.lines, line] }));. Архітектурний контекст - у гайді з headless Shopify.
Частина IV - Міграція React 18 → 19
useFormState→useActionState: перейменований, перенесений зreact-domуreact, доданийisPendingтретім значенням.ReactDOM.renderтаReactDOM.hydrateвидалені: замінити наcreateRootтаhydrateRoot.- TypeScript: оновити
@types/reactдо 19.x. Ref-prop у function components безforwardRef. - Метадані документа:
<title>,<meta>,<link>у компонентах - автоматичний hoisting у<head>. - Asset preloading API:
import { preload, preconnect, prefetchDNS } from 'react-dom'.
Висновок
React 19 - узгоджена архітектурна концепція: мутації описуються як дії, а фреймворк управляє async-циклом. Для команд на Next.js App Router action model та Server Actions - призначена mutation архітектура. Для архітектурного ревʼю або реалізації - сервіс React SPA development | кейси | обговорити проект.
Джерела
- React Team. 'React 19 Release Notes': https://react.dev/blog/2024/12/05/react-19
- React Team. 'useOptimistic Reference': https://react.dev/reference/react/useOptimistic
- React Team. 'use Reference': https://react.dev/reference/react/use
- React Team. 'useActionState Reference': https://react.dev/reference/react/useActionState
- React Team. 'useFormStatus Reference': https://react.dev/reference/react-dom/hooks/useFormStatus
- React Team. 'Server Actions': https://react.dev/reference/rsc/server-actions
- Next.js Team. 'Server Actions and Mutations': https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
