useActionState to hook z React 19, który uruchamia funkcję async (akcję), zapisuje jako stan to, co ona zwróci, i mówi, czy nadal działa. Wywołujesz go jako const [state, formAction, isPending] = useActionState(action, initialState) i przekazujesz formAction do <form>.
Najpierw wyślij pusty formularz: akcja zwraca obiekt błędu i pojawia się komunikat. Potem wpisz adres z @ i wyślij ponownie. Przez sekundę przycisk pokazuje "Subscribing..." i jest wyłączony.
Składnia
const [state, formAction, isPending] = useActionState(action, initialState, permalink?);
actionto funkcja do uruchomienia. React wywołuje ją jakoaction(previousState, ...args). To, co zwróci (albo do czego się rozwiąże, jeśli jest async), staje się nowymstate.initialStateto stan, zanim akcja kiedykolwiek się wykonała. Używaj tego samego kształtu, który zwraca akcja, żeby komponent mógł odczytaćstate.messagetakże przy pierwszym renderowaniu.stateto najnowszy wynik.formActionto opakowana wersja twojej akcji. Przekaż ją do<form action>albo<button formAction>albo wywołaj ją sam.isPendingma wartośćtrueod chwili rozpoczęcia akcji, dopóki się nie skończy.permalinkjest opcjonalny i ma znaczenie tylko dla funkcji serwerowych we frameworku: to adres URL, pod który powinien trafić formularz, jeśli zostanie wysłany przed załadowaniem JavaScriptu.
Akcja dostaje poprzedni stan jako pierwszy argument. To najczęstszy błąd przy przenoszeniu formularza: napisanie async function save(formData) daje ci stary stan w formData, a formData.get rzuca błąd.
Odczyt formularza przez FormData
Gdy formAction jest użyte jako action formularza, React wywołuje twoją akcję z FormData formularza. Znajduje się w nim każde pole z name. Nie potrzebujesz useState dla pól ani handlera onChange i nie wywołujesz e.preventDefault(): React sam obsługuje zdarzenie wysłania.
Odznacz Spicy i wyślij ponownie: klucz spicy znika z wypisanych danych, bo niezaznaczone pole wyboru niczego nie wysyła. Akcja czyta też previousState.count, żeby dodać jeden, i dlatego poprzedni stan jest pierwszy.
Zwracanie błędów walidacji
Walidacja należy do akcji. Zwracaj błędy jako część stanu i zwracaj wpisane przez użytkownika wartości, żeby formularz mógł je przywrócić. Po zakończeniu akcji formularza React resetuje niekontrolowane pola, więc pole bez defaultValue={state.values...} wróciłoby puste po nieudanym wysłaniu.
Wpisz jednoliterowe imię i krótkie hasło, a potem wyślij. Pojawią się oba błędy, a oba pola zachowają to, co wpisałeś. Usuń defaultValue={state.values.name} i wyślij ponownie: pole imienia opróżni się po błędzie.
W prawdziwej aplikacji ostatecznym sędzią niech będzie serwer. Sprawdzenia po stronie klienta dają szybką informację zwrotną, ale każdy może wysłać żądanie bez twojego formularza.
Wywoływanie akcji poza formularzem
formAction to funkcja, więc może ją wywołać też przycisk albo efekt. Gdy wywołujesz ją sam, owiń wywołanie w startTransition. Formularz robi to za ciebie; zwykłe onClick nie, a bez przejścia isPending nie aktualizuje się poprawnie (React wypisuje o tym błąd w trybie deweloperskim).
Kliknij kilka razy Load more. Każde wywołanie zaczyna od stanu, który zwróciło poprzednie, więc strony są dopisywane po kolei. Jeśli wywołasz akcję ponownie, gdy jeszcze działa, React ustawi wywołanie w kolejce i uruchomi je po bieżącym, każde z najnowszym stanem.
Skąd się wziął useActionState
Zanim wydano React 19, ten hook był dostępny w wersjach canary jako useFormState, importowany z react-dom. Zmieniono mu nazwę na useActionState, przeniesiono go do react i dodano wartość isPending. Jeśli znajdziesz taki stary kod, poprawka dotyczy importu i nazwy:
// React canary, before 19
import { useFormState } from 'react-dom';
const [state, formAction] = useFormState(action, initialState);
// React 19
import { useActionState } from 'react';
const [state, formAction, isPending] = useActionState(action, initialState);
Żeby pokazać stan oczekiwania w głęboko zagnieżdżonym przycisku wysyłania, useFormStatus z react-dom odczytuje status formularza rodzica bez propsów. Przegląd React 19 wymienia go razem z innymi funkcjami formularzy.
Błędy i kiedy użyć czegoś innego
Jeśli akcja rzuci błąd, React zamiast aktualizować stan pokaże najbliższą granicę błędów. Błędy, które użytkownik może poprawić, takie jak walidacja albo zajęta nazwa użytkownika, zwracaj jako stan, jak w przykładzie z rejestracją. Prawdziwe awarie niech rzucają błąd.
useActionState służy do wyniku akcji. Dla wartości, która aktualizuje się natychmiast w trakcie działania akcji, na przykład licznika polubień, który ma wzrosnąć po kliknięciu, połącz go z useOptimistic. Dla danych wejściowych, które zmieniają się przy każdym naciśnięciu klawisza i są czytane podczas renderowania, właściwym narzędziem nadal są zwykłe useState i kontrolowane pole.
Częste błędy
Zapomnienie o parametrze poprzedniego stanu. async function save(formData) dostaje poprzedni stan w formData. Dla formularza sygnatura to zawsze (previousState, formData).
Pola bez name. FormData zawiera tylko pola, które mają atrybut name. Pola z samym id brakuje w formData.get(...), które zwraca wtedy null.
Kontrolowane pola wszędzie. Wewnątrz akcji formularza nadal możesz używać value i onChange, ale nie musisz. Niekontrolowane pola z name i defaultValue prościej pasują do akcji, a reset Reacta po wysłaniu dotyczy tylko pól niekontrolowanych.
Odczyt stanu wewnątrz akcji. state z komponentu to wartość z renderowania, które utworzyło handler. Wewnątrz akcji używaj previousState, który zawsze jest wynikiem poprzedniego wywołania, nawet gdy kilka wywołań stało w kolejce.
Rzucanie błędów dla przewidywalnych sytuacji. Rzucony błąd zastępuje formularz najbliższą granicą błędów. Złe hasło to nie awaria; zwróć je jako stan.
Najczęściej zadawane pytania
Co zwraca useActionState?
Tablicę z trzema elementami: bieżący stan (wartość, którą akcja zwróciła ostatnio, albo stan początkowy, zanim akcja się wykonała), nową akcję do przekazania formularzowi albo samodzielnego wywołania oraz isPending, które ma wartość true, dopóki akcja działa.
Jakie argumenty dostaje akcja?
Najpierw poprzedni stan, a potem to, z czym akcja została wywołana. W <form action={formAction}> tym drugim argumentem jest FormData formularza.
Czym różni się useActionState od useFormState?
To ten sam hook. Pojawił się w wersjach canary Reacta jako useFormState w react-dom, w React 19 zmieniono mu nazwę na useActionState i przeniesiono do react, a przy okazji dostał wartość isPending.
Czy mogę używać useActionState bez formularza?
Tak. Wywołaj zwróconą akcję sam, wewnątrz startTransition, na przykład z onClick przycisku. Bez przejścia isPending nie aktualizuje się poprawnie, a React w trybie deweloperskim wypisuje błąd.
Dlaczego mój formularz czyści się po wysłaniu?
Po zakończeniu akcji formularza React resetuje jego niekontrolowane pola, tak jak przeglądarka po zwykłym wysłaniu. Żeby zachować wartość po błędzie, zwróć ją w stanie i przekaż do defaultValue pola.