useFormState - Cette fonctionnalité est disponible dans le dernier Canary

Canary (fonctionnalité expérimentale)

Le Hook useFormState n’est actuellement disponible que sur les canaux de livraison Canary et Expérimental de React. Apprenez-en davantage sur les canaux de livraison React. Par ailleurs, vous aurez besoin d’utiliser un framework qui prenne en charge les React Server Components pour tirer pleinement parti de useFormState.

useFormState est un Hook qui vous permet de mettre à jour l’état sur base du résultat d’une action de formulaire.

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

Référence

useFormState(action, initialState, permalink?)

Appelez useFormState au niveau racine de votre composant pour créer un état de composant qui sera mis à jour lorsqu’une action de formulaire sera invoquée. Vous passez à useFormState une fonction d’action de formulaire existante ainsi qu’un état initial, et il renvoie une nouvelle action que vous pouvez utiliser dans votre formulaire, ainsi que le dernier état en date pour ce formulaire. Cet état sera également passé à la fonction que vous avez fournie.

import { useFormState } from "react-dom";

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

function StatefulForm({}) {
const [state, formAction] = useFormState(increment, 0);
return (
<form>
{state}
<button formAction={formAction}>Incrémenter</button>
</form>
)
}

L’état de formulaire est déterminé par la valeur renvoyée par l’action lors du dernier envoi en date du formulaire. Si le formulaire n’a pas encore été envoyé, il équivaut à l’état initial que vous avez fourni.

Lorsque vous l’utilisez dans une Action Serveur, useFormState permet d’afficher la réponse du serveur pour l’envoi du formulaire avant même que l’hydratation ne soit terminée.

Voir d’autres exemples plus bas.

Paramètres

  • fn : la fonction à appeler lorsque le formulaire est envoyé. Lorsque la fonction est appelée, elle reçoit comme premier argument l’état précédent du formulaire (le initialState que vous avez fourni pour le premier appel, puis, pour les appels ultérieurs, la valeur précédemment renvoyée), suivi par les arguments normalement acceptés par une fonction d’action de formulaire.
  • initialState : la valeur initiale que vous souhaitez pour votre état. Il peut s’agir de n’importe quelle valeur sérialisable. Cet argument est ignoré après l’appel initial de l’action.
  • permalink optionnel : une chaîne de caractères contenant l’URL unique de la page que ce formulaire modifie. Conçu pour une utilisation sur des pages à contenu dynamique (telles que des flux) pour permettre une amélioration progressive : si fn est une Action Serveur et que le formulaire est soumis avant que le bundle JavaScript n’ait fini son chargement, le navigateur ira sur l’URL de permalien fournie, plutôt que sur l’URL de la page courante. Ça permet de garantir que le même composant de formulaire sera produit sur la page destinataire (y compris les infos fn et permalink), afin que React sache comment lui passer l’état. Une fois le formulaire hydraté, ce paramètre n’a plus d’effet.

Valeur renvoyée

useFormState renvoie un tableau avec exactement deux valeurs :

  1. L’état courant. Lors du rendu initial, il s’agira du initialState que vous avez passé. Après que l’action aura été invoquée, il correspondra à la valeur renvoyée par l’action.
  2. Une nouvelle action que vous pouvez passer comme prop action à votre composant form, ou comme prop formAction à tout composant button au sein du formulaire.

Limitations

  • Lorsque vous utilisez un framework prenant en charge les React Server Components, useFormState vous permet de rendre les formulaires interactifs avant même que JavaScript ne soit exécuté côté client. Si vous l’utilisez hors des Server Components, il est équivalent à un état local de composant.
  • La fonction passée à useFormState reçoit un premier argument supplémentaire : l’état précédent ou initial. Sa signature est donc différente de celles des fonctions d’action de formulaire utilisées directement par vos formulaires, sans recours à useFormState.

Utilisation

Utiliser les informations renvoyées par une action de formulaire

Appelez useFormState au niveau racine de votre composant pour accéder à la valeur renvoyée par l’action lors du dernier envoi du formulaire.

import { useFormState } from 'react-dom';
import { action } from './actions.js';

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

useFormState renvoie un tableau avec exactement deux valeurs :

  1. L’état courant du formulaire, qui sera au départ l’état initial que vous aurez fourni, puis une fois le formulaire envoyé, vaudra la valeur de retour de l’action que vous aurez passée.
  2. Une nouvelle action que vous pouvez passer comme prop action à votre form.

Lorsque le formulaire sera envoyé, la fonction d’action que vous aurez fournie sera appelée. Sa valeur de retour deviendra le nouvel état courant du formulaire.

L’action que vous aurez fournie recevra par ailleurs un premier argument supplémentaire, à savoir l’état courant du formulaire. Lors du premier envoi du formulaire, il s’agira de l’état initial que vous aurez fourni, alors que pour les envois ultérieurs, ce sera la valeur renvoyée par le dernier appel en date de l’action. Le reste des arguments est identique à une utilisation de l’action sans useFormState.

function action(currentState, formData) {
// ...
return 'prochain état';
}

Afficher des informations suite à l’envoi d'un formulaire

Exemple 1 sur 2 ·
Afficher des erreurs de formulaire

Pour afficher des messages tels qu’un message d’erreur ou une notification renvoyés par une Action Serveur, enrobez l’action dans un appel à useFormState.

import { useState } from "react";
import { useFormState } from "react-dom";
import { addToCart } from "./actions.js";

function AddToCartForm({itemID, itemTitle}) {
  const [message, formAction] = useFormState(addToCart, null);
  return (
    <form action={formAction}>
      <h2>{itemTitle}</h2>
      <input type="hidden" name="itemID" value={itemID} />
      <button type="submit">Ajouter au panier</button>
      {message}
    </form>
  );
}

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

Dépannage

Mon action n’arrive plus à lire les données envoyées par le formulaire

Lorsque vous enrobez une action avec useFormState, elle reçoit un premier argument supplémentaire. Les données envoyées par le formulaire sont donc présentes comme second argument, plutôt qu’en première position comme en temps normal. Le premier argument ainsi injecté contient l’état actuel du formulaire.

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