Hai hook bù trừ cho nhau khi làm form bằng Server Actions:
useActionState (React, dùng ở Client Component) — bọc một action, giữ state trả về của nó (lỗi validation, kết quả) qua các lần submit.
tsx
const [state, formAction] = useActionState(createUser, { error: null })
return <form action={formAction}>...{state.error && <p>{state.error}</p>}</form>useFormStatus (react-dom) — cho biết form cha đang pending hay không, để vô hiệu nút / hiện spinner.
tsx
function SubmitButton() {
const { pending } = useFormStatus()
return <button disabled={pending}>{pending ? 'Đang gửi…' : 'Gửi'}</button>
}Tại sao useFormStatus phải ở component con: nó đọc trạng thái của <form> cha gần nhất qua context. Nếu gọi ngay trong cùng component chứa <form>, nó không nằm bên trong form đó nên luôn trả pending: false. Vì vậy phải tách nút submit thành component con đặt trong <form>.
Lưu ý: useFormState là tên cũ; React 19 đổi sang useActionState.