Cours 07 - useActionState
useActionState
Section intitulée « useActionState »useActionState: Permet de récupérer une réponse d’une action serveur appelée depuis un formulaire.
Bien qu’une fonction serveur puisse retourner une réponse si elle est appelée depuis un écouteur d’événement ou une fonction dans une composante client, il est impossible de retourner une répose si l’action est appelée depuis un formulaire.
"use client";import {getDataFromAction} from '../_actions/data';
const ComposanteClient = () => {const clickHandler = async () => { const data = await getDataFromAction(); console.log(data);};
return ( <div> <button onClick={clickHandler}>Clic</button> </div>);};useActionState permet de communiquer avec le serveur ainsi que de recevoir ce qui en sera retourné depuis une composante client.
Voici le code de départ:
"use client";import {formSubmitAction} from '../_actions/data';
const ComposanteClientAvecFormulaire = () => { return ( <form action={formSubmitAction}> <input type="text" name="texte"/> <button>Soumettre</button> </form> );};"use server";export const formSubmitAction = async (formData) => { const text = formData.get('texte'); // fait qqc avec le texte // ne peut rien retourner au formulaire};On importe tout d’abord useActionState et on l’initialise (côté client):
import {useActionState} from 'react';
const [state, formAction, isPending] = useActionState(actionServeur, stateInitial);Précisions
Section intitulée « Précisions »- actionServeur: Référence à l’action serveur telle que reçu en props ou importée (fonction contenant la mention ‘use server’)
- stateInitial: Valeurs utiles à la vérification de l’état de l’exécution côté serveur. Ex:
{isLoading: true, error: null, data: null, success: false}. On pourrait aussi passer des valeurs utiles à l’exécution côté serveur. Échanges de données entre le client et le serveur. - formAction: La nouvelle action à lier au formulaire. Attention, un paramètre supplémentaire sera envoyé à l’action serveur par la suite.
- state: Valeurs de l’état passé dans stateInitial en temps réel. Sera modifié par ce que l’action côté serveur retournera.
- isPending: booléen indiquant si la requête est en cours (pratique pour afficher un spinner ou un skeleton)
ex:
"use client";import {formSubmitAction} from '../_actions/data';import {useActionState} from 'react';
const ComposanteClientAvecFormulaire = () => {
// fromServerState contient [] à l'initialisation const [resultats, formAction, isPending] = useActionState(formSubmitAction, []);
// on échange l'action de départ avec celle reçue par l'appel de useActionState return ( <div> <form action={formAction}> <input type="text" name="texte"/> <button>Soumettre</button> </form>
<div> {resultats.map(r => (<div key={r.id}>{r.nom}</div>))} </div>
</div> );};"use server";
// prevState contient le tableau vide (le state reçu pourrait être utile dans certains cas)export const formSubmitAction = async (prevState, formData) => { const text = formData.get('texte'); // recherche le nom dans un annuaire et retourne les résultats const results = await getResultsFromASource(); return results;};ou
"use client";import {useActionState} from 'react'import {incrementAction} from '../_actions/data.js';
const FormulaireAvecState({}) { // valeur contiendra 0 au départ const [valeur, formAction] = useActionState(incrementAction, 0); return ( <form> {valeur} {/* affiche la valeur du compteur*/} <button formAction={formAction}>Incrémenter</button> </form> );}"use server";// prevState = 0 la première foisexport const incrementAction = async (prevState, formData) => { return prevState + 1;};