React 19: огляд нового — Actions, useOptimistic, use(), ref у props
React 19 (грудень 2024) — найбільший реліз з 16.8 (hooks). Принципово нові концепції: Actions, useOptimistic, use() як promise reader, ref як prop. Розбираємо що змінилось і як це впливає на код у 2026.
Що нового в React 19
| Фіча | Що дає |
|---|---|
| Actions | Native async-функції у формах + автоматичні pending/error states |
| useOptimistic | Тимчасовий optimistic state доки чекаємо server |
| useActionState | Заміна useFormState для Server Actions |
| use() | Читання promise / context прямо у render |
| ref як prop | Більше не потрібен forwardRef для простих компонентів |
| Document metadata | <title>, <meta> прямо у компонентах |
| Stylesheet precedence | Сортування CSS під капотом |
| Async transitions | useTransition тепер працює з async функціями |
Actions — нова модель async-роботи
До 19: писав useState(loading), useState(error), try/catch у handler. Багато boilerplate.
Тепер:
function UpdateNameForm() {
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
const name = formData.get("name");
const result = await updateName(name);
if (result.error) return result.error;
return null;
},
null,
);
return (
<form action={submitAction}>
<input name="name" />
<button disabled={isPending}>
{isPending ? "Зберігаю…" : "Зберегти"}
</button>
{error && <p>{error}</p>}
</form>
);
}
Pending і error tracking — автоматично. Boilerplate зник.
useOptimistic — миттєвий feedback
UI оновлюється до відповіді сервера. Якщо сервер впав — rollback.
function MessageList({ messages, sendMessage }) {
const [optimisticMessages, addOptimistic] = useOptimistic(
messages,
(state, newMessage) => [...state, { text: newMessage, pending: true }]
);
async function action(formData) {
addOptimistic(formData.get("text"));
await sendMessage(formData.get("text"));
}
return (
<>
{optimisticMessages.map((m, i) => (
<p key={i} style={{ opacity: m.pending ? 0.5 : 1 }}>{m.text}</p>
))}
<form action={action}>...</form>
</>
);
}
UX як у Twitter — повідомлення з'являється миттєво.
use() — читання promise у render
До 19: const data = await fetch(...) лише у Server Component. У клієнті — useEffect + useState.
Тепер у Client Component:
function UserProfile({ userPromise }) {
const user = use(userPromise); // suspend поки promise не resolved
return <h1>{user.name}</h1>;
}
// Wrapper:
<Suspense fallback={<Spinner />}>
<UserProfile userPromise={fetchUser(id)} />
</Suspense>
use() працює з:
- Promise (suspend поки не resolve)
- Context (заміна useContext, можна викликати умовно)
ref як prop — без forwardRef
До 19:
const Input = forwardRef<HTMLInputElement, Props>((props, ref) => (
<input ref={ref} {...props} />
));
Після 19:
function Input({ ref, ...props }: Props & { ref: Ref<HTMLInputElement> }) {
return <input ref={ref} {...props} />;
}
forwardRef — більше не потрібен. Чистіше і typed краще.
Document metadata — без next/head
function ProductPage({ product }) {
return (
<>
<title>{product.name}</title>
<meta name="description" content={product.description} />
<h1>{product.name}</h1>
</>
);
}
React автоматично переносить ці елементи у <head>. Працює і на сервері, і на клієнті.
⚠ В Next.js — використовуй metadata export або generateMetadata для SEO. React 19 docu metadata — fallback для не-Next-додатків.
Compiler — auto-memoization (Preview)
React Compiler (поки RC у 2025-2026) автоматично робить memo/useMemo/useCallback. Більше не потрібно вручну:
// До compiler'а:
const expensive = useMemo(() => compute(a, b), [a, b]);
const handleClick = useCallback(() => doX(c), [c]);
// З compiler'ом:
const expensive = compute(a, b);
const handleClick = () => doX(c);
// Compiler сам перетворює це у memoized версію
У 2026 поступово стає default. Перевір react-compiler ESLint plugin.
Що НЕ змінилось / часті помилки
useStateпрацює як завждиuseEffect— без змін, не використовуй його для data fetching (use() + Suspense)- Class components — все ще працюють, але legacy
- React 18 patterns — сумісні
Setup нового проєкту з React 19
npx create-next-app@latest my-app --typescript --app --tailwind
cd my-app
npm install
npm run dev
Next.js 15+ використовує React 19 за умовчанням.
Тест: перевір себе нижче
Інтерактивні задачі під уроком — single-choice, multi-choice, code. Проходь, отримуй ✓ на кожний урок.