useActionState
useActionState es un Hook de React que te permite actualizar el estado basándote en el resultado de una acción de formulario.
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);Referencia
useActionState(action, initialState, permalink?)
Llama a useActionState en el nivel superior de tu componente para crear un estado del componente que se actualiza cuando se invoca una acción de formulario. Le pasas a useActionState una función de acción de formulario existente junto con un estado inicial, y te devuelve una nueva acción que puedes usar en tu formulario, junto con el estado más reciente del formulario y si la acción aún está pendiente. El estado más reciente del formulario también se pasa a la función que proporcionaste.
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>
)
}El estado del formulario es el valor que devuelve la acción la última vez que se envió el formulario. Si el formulario aún no se ha enviado, es el estado inicial que proporcionaste.
Si se usa con una Función de Servidor, useActionState permite mostrar la respuesta del servidor al enviar el formulario incluso antes de que la hidratación haya completado.
Parámetros
fn: La función que se llamará cuando se envíe el formulario o se presione el botón. Cuando se llama a la función, recibirá el estado previo del formulario (inicialmente elinitialStateque pasaste, y posteriormente su valor de retorno anterior) como primer argumento, seguido de los argumentos que una acción de formulario normalmente recibe.initialState: El valor que deseas que tenga el estado inicialmente. Puede ser cualquier valor serializable. Este argumento se ignora después de que la acción se invoque por primera vez.- opcional
permalink: Un string que contiene la URL única de la página que este formulario modifica. Para usar en páginas con contenido dinámico (por ejemplo: feeds) en conjunto con mejora progresiva: sifnes una función de servidor y el formulario se envía antes de que el paquete de JavaScript se cargue, el navegador navegará a la URL de permalink especificada, en lugar de la URL de la página actual. Asegúrate de que el mismo componente de formulario se renderice en la página de destino (incluyendo la misma acciónfnypermalink) para que React sepa cómo pasar el estado. Una vez que el formulario se haya hidratado, este parámetro no tiene efecto.
Devuelve
useActionState devuelve un array con los siguientes valores:
- El estado actual. Durante el primer renderizado, coincidirá con el
initialStateque hayas pasado. Después de que la acción se invoque, coincidirá con el valor que devolvió la acción. - Una nueva acción que puedes pasar como la prop
actiona tu componenteformo como la propformActiona cualquier componentebuttondentro del formulario. La acción también puede llamarse manualmente dentro destartTransition. - El flag
isPendingque te indica si hay una Transición pendiente.
Advertencias
- Cuando se usa con un framework que soporta React Server Components,
useActionStatepermite hacer los formularios interactivos antes de que JavaScript se haya ejecutado en el cliente. Cuando se usa sin Server Components, es equivalente al estado local del componente. - La función pasada a
useActionStaterecibe un argumento extra, el estado previo o inicial, como su primer argumento. Esto hace que su firma sea diferente a si se usara directamente como una acción de formulario sin usaruseActionState.
Uso
Usar información devuelta por una acción de formulario
Llama a useActionState en el nivel superior de tu componente para acceder al valor de retorno de una acción desde la última vez que se envió el formulario.
import { useActionState } from 'react';
import { action } from './actions.js';
function MyComponent() {
const [state, formAction] = useActionState(action, null);
// ...
return (
<form action={formAction}>
{/* ... */}
</form>
);
}useActionState devuelve un array con los siguientes elementos:
- El estado actual del formulario, que inicialmente se establece con el estado inicial que proporcionaste, y después de enviar el formulario se establece con el valor de retorno de la acción que proporcionaste.
- Una nueva acción que pasas a
<form>como su propactiono la llamas manualmente dentro destartTransition. - Un estado pendiente que puedes utilizar mientras tu acción se está procesando.
Cuando se envía el formulario, se llamará a la función de acción que proporcionaste. Su valor de retorno se convertirá en el nuevo estado actual del formulario.
La acción que proporcionaste también recibirá un nuevo primer argumento, el estado actual del formulario. La primera vez que se envía el formulario, este será el estado inicial que proporcionaste, mientras que en envíos posteriores, será el valor de retorno de la última vez que se llamó a la acción. El resto de los argumentos son los mismos que si no se hubiera usado useActionState.
function action(currentState, formData) {
// ...
return 'next state';
}Ejemplo 1 de 2: Mostrar errores de formulario
Para mostrar mensajes como un mensaje de error o un toast devuelto por una Función de Servidor, envuelve la acción en una llamada a 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" /> </> ) }
Solución de problemas
Mi acción ya no puede leer los datos del formulario enviado
Cuando envuelves una acción con useActionState, recibe un argumento extra como su primer argumento. Los datos del formulario enviado son por lo tanto su segundo argumento en lugar de ser el primero como sería normalmente. El nuevo primer argumento que se agrega es el estado actual del formulario.
function action(currentState, formData) {
// ...
}