useActionState é um Hook que permite que você atualize o estado com base no resultado de uma ação 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 superior do seu componente para criar um estado do componente que é atualizado quando uma ação de formulário é invocada. Você passa para o useActionState uma função de ação de formulário existente, bem como um estado inicial, e ele retorna uma nova ação que você usa no seu formulário, juntamente com o estado atual do formulário e se a ação 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 ação quando o formulário foi enviado pela última vez. Se o formulário ainda não foi enviado, é o estado inicial que você passa.

Quando usado com uma Função de Servidor, useActionState permite que a resposta do servidor ao enviar o formulário seja exibida mesmo antes da hidratação ser concluída.

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 ação é invocada pela primeira vez.
  • opcional permalink: Uma string contendo 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 função de servidor e o formulário é enviado antes do carregamento do bundle JavaScript, o navegador navegará para a URL de permalink especificada, em vez da URL da página atual. Garanta que o mesmo componente de formulário seja renderizado na página de destino (incluindo a mesma fn de ação e permalink) para que o React saiba como passar o estado. Uma vez que o formulário tenha sido hidratado, este parâmetro não tem efeito.

Retornos

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 ação for invocada, ele corresponderá ao valor retornado pela action.
  2. Uma nova ação 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 ação 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 ação de formulário sem usar useActionState.

Uso

Usando informações retornadas por uma ação de formulário

Chame useActionState no nível superior 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 ação que você forneceu.
  2. Uma nova ação 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 ação está processando.

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

A ação 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 ação 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) {
// ...
}