useActionState
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?);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.
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 oinitialStateque 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: sefné 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 mesmafnde ação epermalink) 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:
- O estado atual. Durante a primeira renderização, ele corresponderá ao
initialStateque você passou. Depois que a ação for invocada, ele corresponderá ao valor retornado pela action. - Uma nova ação que você pode passar como a prop
actionpara seu componenteformou a propformActionpara qualquer componentebuttondentro do formulário. A ação também pode ser chamada manualmente dentro destartTransition. - A flag
isPendingque informa se existe uma Transition pendente.
Ressalvas
- Quando usado com um framework que oferece suporte a React Server Components,
useActionStatepermite 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
useActionStaterecebe 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 usaruseActionState.
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:
- 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.
- Uma nova ação que você passa para o
<form>como sua propactionou chama manualmente dentro destartTransition. - 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';
}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) {
// ...
}