Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як працює useActionState і як показати результат чи помилки відправки форми?

useActionState (React 19) - стан, що оновлюється результатом дії (Action). Зручно для форм: дія відправляє дані, а повернене значення стає новим станом - повідомленням про успіх чи помилками.

import { useActionState } from 'react';

async function subscribe(previousState, formData) {
  const response = await fetch('/api/subscribe', {
    method: 'POST',
    headers: { Accept: 'application/json' },
    body: formData,
  });

  if (response.status === 422) {
    const { errors } = await response.json();
    return { errors, email: formData.get('email') };
  }

  return { success: true };
}

function SubscribeForm() {
  const [state, formAction, isPending] = useActionState(subscribe, { errors: {} });

  if (state.success) return <p>Дякуємо за підписку!</p>;

  return (
    <form action={formAction}>
      <input name="email" type="email" defaultValue={state.email} />
      {state.errors?.email && <p role="alert">{state.errors.email[0]}</p>}
      <button disabled={isPending}>{isPending ? 'Надсилаємо...' : 'Підписатися'}</button>
    </form>
  );
}

Як працює:

  • useActionState(reducerAction, initialState) повертає [state, dispatchAction, isPending];
  • reducerAction(previousState, payload) - як редюсер у useReducer, але може бути асинхронним і мати побічні ефекти. Для форми payload - це FormData;
  • isPending - чи виконується дія;
  • кілька викликів ставляться в чергу й виконуються послідовно: кожен отримує результат попереднього. Подвійне натискання не дасть двох паралельних запитів у довільному порядку;
  • dispatchAction треба викликати з дії: передати в <form action> чи <button formAction>, або обгорнути в startTransition.

Пастки:

  • форма скидається після успішної дії - неконтрольовані поля очищуються. Щоб не губити введене при помилці, повертайте значення в стані (defaultValue={state.email}, як у прикладі);
  • кинутий виняток у дії скасовує всі дії в черзі й показує найближчий Error Boundary. Очікувані помилки (валідація) - повертати як стан, а не кидати;
  • початковий стан і тип результату мають збігатися - інакше TypeScript скаржиться на невідповідність типів.

Server Functions: з Next.js чи іншим RSC-фреймворком дія може бути серверною функцією ('use server') - тоді форма працює навіть до завантаження JavaScript (третій аргумент permalink).

Докладніше в документації: useActionState

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання