useActionState é um Hook que permite que você atualize o estado com base no resultado de uma action de formulário.

const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);

Note

Em versões anteriores do React Canary, esta API fazia parte do React DOM e era chamada de useFormState.


Referência

useActionState(action, initialState, permalink?)

Chame useActionState no nível raiz do seu componente para criar um estado de componente que é atualizado quando uma action de formulário é invocada. Você passa para o useActionState uma função de action de formulário existente, bem como um estado inicial, e ele retorna uma nova action que você usa no seu formulário, juntamente com o estado atual do formulário e se a Action ainda está pendente. O estado atual do formulário também é passado para a função que você forneceu.

import { useActionState } from "react";

async function increment(previousState, formData) {
return previousState + 1;
}

function StatefulForm({}) {
const [state, formAction] = useActionState(increment, 0);
return (
<form>
{state}
<button formAction={formAction}>Increment</button>
</form>
)
}

O estado do formulário é o valor retornado pela action quando o formulário foi enviado pela última vez. Se o formulário ainda não foi enviado, é o estado inicial que você passa.

Se usado com uma Server Function, useActionState permite que a resposta do servidor do envio do formulário seja exibida mesmo antes da conclusão da hidratação.

Veja mais exemplos abaixo.

Parâmetros

  • fn: A função a ser chamada quando o formulário é enviado ou o botão pressionado. Quando a função é chamada, ela receberá o estado anterior do formulário (inicialmente o initialState que você passa, subsequentemente seu valor de retorno anterior) como seu primeiro argumento, seguido pelos argumentos que uma ação de formulário normalmente recebe.
  • initialState: O valor que você deseja que o estado seja inicialmente. Pode ser qualquer valor serializável. Este argumento é ignorado depois que a action é invocada pela primeira vez.
  • opcional permalink: Uma string que contém a URL exclusiva da página que este formulário modifica. Para uso em páginas com conteúdo dinâmico (por exemplo: feeds) em conjunto com aprimoramento progressivo: se fn é uma server function e o formulário é enviado antes que o bundle JavaScript seja carregado, o navegador navegará para a URL da permalink especificada, em vez da URL da página atual. Certifique-se de que o mesmo componente de formulário seja renderizado na página de destino (incluindo a mesma action fn e permalink) para que React saiba como passar o state. Depois que o formulário for hidratado, este parâmetro não terá efeito.

Retorna

useActionState retorna um array com os seguintes valores:

  1. O estado atual. Durante a primeira renderização, ele corresponderá ao initialState que você passou. Depois que a action for invocada, ele corresponderá ao valor retornado pela action.
  2. Uma nova action que você pode passar como a prop action para seu componente form ou a prop formAction para qualquer componente button dentro do formulário. A action também pode ser chamada manualmente dentro de startTransition.
  3. A flag isPending que informa se existe uma Transition pendente.

Ressalvas

  • Quando usado com um framework que oferece suporte a React Server Components, useActionState permite que você torne os formulários interativos antes que o JavaScript tenha sido executado no cliente. Quando usado sem Server Components, é equivalente ao estado local do componente.
  • A função passada para useActionState recebe um argumento extra, o estado anterior ou inicial, como seu primeiro argumento. Isso torna sua assinatura diferente do que se fosse usado diretamente como uma action de formulário sem usar useActionState.

Uso

Usando informações retornadas por uma action de formulário

Chame useActionState no nível raiz do seu componente para acessar o valor de retorno de uma action da última vez que um formulário foi enviado.

import { useActionState } from 'react';
import { action } from './actions.js';

function MyComponent() {
const [state, formAction] = useActionState(action, null);
// ...
return (
<form action={formAction}>
{/* ... */}
</form>
);
}

useActionState retorna um array com os seguintes itens:

  1. O estado atual do formulário, que é inicialmente definido como o estado inicial que você forneceu e, após o formulário ser enviado, é definido como o valor de retorno da action que você forneceu.
  2. Uma nova action que você passa para o <form> como sua prop action ou chama manualmente dentro de startTransition.
  3. Um estado pendente que você pode utilizar enquanto sua action está processando.

Quando o formulário é enviado, a função action que você forneceu será chamada. Seu valor de retorno se tornará o novo estado atual do formulário.

A action que você fornece também receberá um novo primeiro argumento, ou seja, o estado atual do formulário. Na primeira vez que o formulário for enviado, este será o estado inicial que você forneceu, enquanto com envios subsequentes, será o valor de retorno da última vez que a action foi chamada. O restante dos argumentos são os mesmos de se useActionState não tivesse sido usado.

function action(currentState, formData) {
// ...
return 'next state';
}

Exibir informações após o envio de um formulário

Example 1 of 2:
Exibir erros de formulário

Para exibir mensagens como uma mensagem de erro ou toast que é retornado por uma Server Function, envolva a action em uma chamada para useActionState.

import { useActionState, useState } from "react";
import { addToCart } from "./actions.js";

function AddToCartForm({itemID, itemTitle}) {
  const [message, formAction, isPending] = useActionState(addToCart, null);
  return (
    <form action={formAction}>
      <h2>{itemTitle}</h2>
      <input type="hidden" name="itemID" value={itemID} />
      <button type="submit">Add to Cart</button>
      {isPending ? "Loading..." : message}
    </form>
  );
}

export default function App() {
  return (
    <>
      <AddToCartForm itemID="1" itemTitle="JavaScript: The Definitive Guide" />
      <AddToCartForm itemID="2" itemTitle="JavaScript: The Good Parts" />
    </>
  )
}

Solução de problemas

Minha action não consegue mais ler os dados do formulário enviado

Quando você envolve uma action com useActionState, ela recebe um argumento extra como seu primeiro argumento. Os dados do formulário enviado são, portanto, seu segundo argumento em vez de seu primeiro, como seria normalmente. O novo primeiro argumento que é adicionado é o estado atual do formulário.

function action(currentState, formData) {
// ...
}