'use server' - Cette fonctionnalité est disponible dans le dernier Canary

Canary (fonctionnalité expérimentale)

'use server' n’est utile que si vous utilisez React Server Components ou créez une bibliothèque compatible avec eux.

'use server' marque les fonctions côté serveur qui peuvent être appelées par du code React côté client.


Référence

'use server'

Ajoutez 'use server'; tout en haut d’une fonction asynchrone pour indiquer que cette fonction peut être appelée par du code côté client. Nous appelons ces fonctions des Actions Serveur.

async function addToCart(data) {
'use server';
// ...
}

Lorsque vous appelez une Action Serveur côté client, elle fait une requête réseau auprès du serveur en incluant une copie sérialisée des arguments que vous avez passés. Si l’Action Serveur renvoie une valeur, cette valeur sera sérialisée puis renvoyée au client.

Plutôt que de marquer chaque fonction concernée avec 'use server', vous pouvez ajouter cette directive tout en haut d’un fichier afin d’en marquer tous les exports comme des Actions Serveur utilisables n’importe où, y compris au travers d’imports par du code client.

Limitations

  • 'use server' doit être placé au tout début de la fonction ou du module concerné ; au-dessus notamment de tout code, y compris les imports (mais il peut y avoir des commentaires avant les directives). La directive doit utiliser des apostrophes (') ou guillemets ("), mais pas des backticks (`).
  • 'use server' ne peut être utilisé qu’au sein de fichiers côté serveur. Les Actions Serveur résultantes peuvent être passées à des Composants Client au moyen des props. Consultez la liste des types sérialisables.
  • Pour importer une Action Serveur depuis du code côté client, la directive doit obligatoirement être utilisée au niveau du module.
  • Dans la mesure où les appels réseau sous-jacents sont forcément asynchrones, 'use server' n’est utilisable qu’au sein de fonctions asynchrones.
  • Considérez toujours les arguments de vos Actions Serveur comme des données non validées, et soumettez toute mutation à un processus d’autorisation. Allez voir les considérations sécuritaires.
  • Les Actions Serveur devraient toujours être appelées au sein d’une Transition. Les Actions Serveur passées à <form action> ou formAction seront automatiquement enrobées par une transition.
  • Les Actions Serveur sont conçues pour des mutations qui mettent à jour l’état côté serveur ; il est déconseillé de s’en servir pour du simple chargement de données. Dans cet esprit, les frameworks qui implémentent les Actions Serveur traitent généralement une action à la fois et ne permettent pas la mise en cache de leur valeur renvoyée.

Considérations sécuritaires

Les arguments passés aux Actions Serveur sont entièrement contrôlés par le côté client. Pour des raisons de sécurité, traitez-les toujours comme des données non validées, et assurez-vous d’en vérifier la structure et le contenu, et de procéder à leur échappement lorsque c’est nécessaire.

Par ailleurs, et quelle que soit l’Action Serveur, assurez-vous toujours que l’utilisateur authentifié a le droit d’effectuer cette action.

En construction

Pour éviter le renvoi de données sensibles par une Action Serveur, nous proposons des API expérimentales empêchant l’envoi vers du code côté client de valeurs et objets uniques « ternis ».

Allez jeter un coup d’œil à experimental_taintUniqueValue et experimental_taintObjectReference.

Arguments et valeurs renvoyées sérialisables

Lorsque du code côté client appelle l’Action Serveur au travers du réseau, tout argument passé aura besoin d’être sérialisé.

Voici les types pris en charge pour les arguments d’une Action Serveur :

En particulier, les types suivants ne sont pas pris en charge :

  • Les éléments React, ainsi que JSX
  • Les fonctions, y compris les fonctions composants, et de façon plus générale toute fonction qui ne serait pas une Action Serveur
  • Les classes
  • Les objets de quelque classe que ce soit (hormis les classes natives explicitement listées plus haut) ainsi que les objets ayant un prototype nul
  • Les symboles non inscrits au global, ex. Symbol('my new symbol')

Les valeurs renvoyées sérialisables sont les mêmes que pour les props sérialisables d’un Composant Client agissant comme « point de césure » entre le code côté client et le code côté serveur.

Utilisation

Les Actions Serveur dans les formulaires

Le cas le plus courant d’Actions Serveur consiste à appeler des fonctions côté serveur pour modifier des données. Dans le navigateur, on utilise traditionnellement l’élément HTML form pour permettre à l’utilisateur de demander une mutation de données. Avec les React Server Components, React prend désormais pleinement en charge les Actions Serveur dans les formulaires.

Voici un formulaire qui permet à l’utilisateur de réserver un identifiant.

// App.js

async function requestUsername(formData) {
'use server';
const username = formData.get('username');
// ...
}

export default function App() {
return (
<form action={requestUsername}>
<input type="text" name="username" />
<button type="submit">Réserver</button>
</form>
);
}

Dans cet exemple, requestUsername est une Action Serveur passée à un <form>. Lorsque l’utilisateur envoie le formulaire, une requête réseau est faite à l’Action Serveur requestUsername. Puisque celle-ci est appelée au travers d’un formulaire, React fournit les FormData du formulaire comme premier argument à l’Action Serveur.

Grâce au passage d’une Action Serveur comme action du formulaire, React peut faire l’amélioration progressive du formulaire. Ça signifie que les formulaires peuvent être envoyés avant même que le bundle JavaScript ne soit chargé et exécuté.

Gérer les valeurs renvoyées dans les formulaires

Pour revenir à notre formulaire de réservation d’identifiant, il peut arriver que l’identifiant ne soit plus disponible. requestUsername devrait nous indiquer si elle a réussi ou non sa réservation.

Pour mettre à jour l’UI sur base du résultat d’une Action Serveur, tout en proposant une amélioration progressive, utilisez useFormState.

// requestUsername.js
'use server';

export default async function requestUsername(formData) {
const username = formData.get('username');
if (canRequest(username)) {
// ...
return 'réussie';
}
return 'échouée';
}
// UsernameForm.js
'use client';

import { useFormState } from 'react-dom';
import requestUsername from './requestUsername';

function UsernameForm() {
const [returnValue, action] = useFormState(requestUsername, 'n/d');

return (
<>
<form action={action}>
<input type="text" name="username" />
<button type="submit">Réserver</button>
</form>
<p>Résultat de la dernière réservation : {returnValue}</p>
</>
);
}

Remarquez que useFormState, au même titre que la plupart des Hooks, ne peut être appelé que depuis du code côté client.

Appeler une Action Serveur hors d’un <form>

Les Actions Serveur exposent en pratique des points d’entrée côté serveur, et peuvent être appelées n’importe où dans du code client.

Pour utiliser une Action Serveur hors d’un formulaire, appelez l’Action Serveur au sein d’une Transition, ce qui vous permettra non seulement d’afficher un indicateur de chargement, mais aussi de réaliser des mises à jour optimistes d’état et de gérer les éventuelles erreurs. Les formulaires enrobent automatiquement vos Actions Serveur dans une transition.

import incrementLike from './actions';
import { useState, useTransition } from 'react';

function LikeButton() {
const [isPending, startTransition] = useTransition();
const [likeCount, setLikeCount] = useState(0);

const onClick = () => {
startTransition(async () => {
const currentCount = await incrementLike();
setLikeCount(currentCount);
});
};

return (
<>
<p>Total des Likes : {likeCount}</p>
<button onClick={onClick} disabled={isPending}>Like</button>;
</>
);
}
// actions.js
'use server';

let likeCount = 0;
export default async function incrementLike() {
likeCount++;
return likeCount;
}

Pour obtenir la valeur renvoyée par une Action Serveur, vous aurez besoin d’un await sur la promesse renvoyée.