React Server Components expliqués : use client, Server Actions, Suspense | We.Inc
Les React Server Components en termes simples : un schéma de la frontière, les règles de "use client", la récupération de données, les server actions pour les formulaires avec useActionState, le streaming avec Suspense et les solutions aux erreurs courantes.
Les React Server Components expliqués
Les React Server Components s'affichent sur le serveur et envoient au navigateur une interface terminée, pas leur JavaScript. Ils peuvent attendre des données avec await et utiliser des secrets directement. Tout ce qui est interactif va dans un Client Component, un fichier qui commence par "use client". Les formulaires peuvent appeler des server functions marquées "use server", et Suspense fait arriver les parties lentes plus tard en streaming.
Les trois directives et hooks dont vous avez besoin
Écrivez
Signification
(rien)
Server Component, dans le Next.js App Router
"use client"
Ce fichier et ses imports s'exécutent aussi dans le navigateur
"use server"
Ces fonctions exportées s'exécutent sur le serveur quand on les appelle
<Suspense>
Affiche un fallback ici pendant que cette partie se charge
Commencez par le schéma : les cases bleues restent sur le serveur, les orange sont aussi envoyées au navigateur. Copiez ensuite les patterns pour les données, les formulaires et le streaming, et servez-vous du tableau des erreurs quand le build se plaint.
Laissez les composants en Server Components par défaut.
Récupérez les données dans des Server Components async, au plus près de l'endroit où elles s'affichent.
Ajoutez "use client" seulement aux petites parties qui ont besoin de state ou de gestionnaires.
Utilisez des server functions pour les formulaires et les mutations, avec useActionState pour le retour à l'utilisateur.
Entourez les parties lentes de Suspense, ou ajoutez un loading.tsx, pour que la page s'affiche vite.
Descendez "use client" le plus bas possible dans l'arbre ; une frontière près de la racine rend toute l'application de nouveau côté client.
Validez chaque entrée de server function. C'est un endpoint public, même si seul votre formulaire l'appelle.
Vérifiez qui est l'utilisateur dans chaque server function, pas seulement sur la page qui affiche le formulaire.
Passez les Server Components aux Client Components en tant que children au lieu de les importer.
Évitez les cascades de requêtes : lancez ensemble les fetchs indépendants avec Promise.all.
Questions fréquentes
Les Server Components sont-ils la même chose que le rendu côté serveur ?
Non. Le rendu côté serveur transforme n'importe quel composant en HTML pour le premier chargement et envoie quand même son JavaScript. Un Server Component n'envoie jamais son JavaScript ; seul son résultat est envoyé. Les Client Components sont toujours rendus côté serveur pour le premier chargement.
Faut-il Next.js pour utiliser les Server Components ?
Il faut un framework ou un bundler qui les prend en charge. Le Next.js App Router est le plus utilisé ; quelques autres, comme Waku, les prennent aussi en charge.
Un Client Component peut-il importer un Server Component ?
Non, un import depuis un fichier client fait entrer le module dans le bundle client. Passez plutôt le Server Component comme children ou comme autre prop depuis un parent Server Component.
Quelle est la différence entre server actions et server functions ?
React appelle désormais server function toute fonction marquée "use server". Quand elle sert d'action de formulaire ou est appelée dans une transition, on parle souvent de server action. Next.js a employé le terme server actions en premier.
useActionState fonctionne-t-il sans JavaScript ?
Le formulaire envoie quand même vers la server function avant l'hydratation, il est donc bien soumis. L'état d'attente et le message en ligne ont besoin de JavaScript, assurez-vous donc que le serveur renvoie une page utile dans les deux cas.
Pourquoi ce modèle aide un site web
La plus grande partie d'une page marketing ou de contenu ne change jamais après son rendu : titres, texte, images, fiches produit. En Server Components, elles ne coûtent aucun JavaScript, ce qui laisse le thread principal libre pour les quelques parties interactives et améliore généralement l'Interaction to Next Paint.
Checklist de sécurité pour les server functions
Traitez chaque fonction "use server" comme une route d'API : vérifiez la session, validez l'entrée avec un schéma, vérifiez que l'utilisateur a le droit de modifier cet enregistrement, et ne renvoyez que ce dont le client a besoin. Ne renvoyez jamais de lignes de base de données contenant des champs que l'utilisateur ne doit pas voir.
Ce qui s'exécute où
Où chaque chose peut s'exécuter
Vous devez
Server Component
Client Component
Lire une base de données ou une clé d'API secrète
Oui
Non (exposerait le secret)
Faire un await sur des données directement dans le composant
Oui (composant async)
Non
useState, useEffect, useReducer
Non
Oui
onClick, onChange et autres gestionnaires
Non
Oui
window, localStorage, API du navigateur
Non
Oui, après le montage
N'envoyer aucun JavaScript pour le composant
Oui
Non
Afficher l'autre type
Oui, affiche des Client Components
Seulement des Server Components passés en children ou en props
Server Components et Client Components
Un Server Component qui lit des données
Dans l'App Router, les composants sont des Server Components sauf indication contraire. Ils peuvent être async et parler directement à la base de données ; rien de ce code n'atteint le navigateur.
Un Client Component pour l'interaction
"use client" tout en haut marque une frontière : ce fichier et tout ce qu'il importe sont inclus dans le bundle du navigateur. Gardez ces fichiers petits et poussez-les vers les feuilles de l'arbre.
Faire passer un Server Component à travers un Client Component
Un Client Component ne peut pas importer un Server Component, mais il peut en recevoir un en children. Le serveur le rend d'abord et le client ne fait que placer le résultat.
Éviter d'envoyer des secrets au navigateur par accident
Importer le package server-only fait échouer le build si un fichier client importe un jour ce module, une clé d'API ne peut donc pas fuiter par un import maladroit.
Server functions pour les formulaires
Un formulaire qui envoie vers une server function
"use server" transforme une fonction async en endpoint que le formulaire peut appeler. Le formulaire fonctionne avant le chargement du JavaScript, car c'est un vrai envoi de formulaire.
État d'attente et résultat avec useActionState
useActionState (React 19) encapsule la server function et vous donne son dernier résultat et un indicateur d'attente, pour que le bouton affiche Envoi en cours et que le message apparaisse sans state supplémentaire.
Rafraîchir les données de la page après un changement
Après une mutation, indiquez à Next.js quelles données de chemin sont périmées pour que le rendu suivant affiche le changement.
Le streaming avec Suspense
Diffuser la partie lente avec Suspense
Entourez un Server Component lent de Suspense. Le reste de la page est envoyé tout de suite avec le fallback en place, et la partie lente arrive en streaming quand ses données sont là.
loading.tsx pour toute une route
Un fichier loading.tsx à côté de page.tsx entoure cette page d'une frontière Suspense pour vous, la navigation l'affiche donc tout de suite pendant que les données de la page se chargent.
Lancer les requêtes ensemble
Attendre un fetch après l'autre dans un Server Component additionne leurs durées. Lancez-les en même temps et attendez les deux.
Les erreurs que vous rencontrerez
Erreurs courantes et solution
Ce que vous voyez
Cause
Solution
Un hook comme useState ne fonctionne que dans un Client Component
Un hook dans un fichier sans "use client"
Déplacez la partie interactive dans son propre fichier qui commence par "use client"
Les gestionnaires d'événements ne peuvent pas être passés aux props d'un Client Component
onClick passé depuis un Server Component
Placez le gestionnaire dans le Client Component, ou passez plutôt une server function
Les fonctions ne peuvent pas être passées directement aux Client Components
Une fonction ordinaire passée en prop à travers la frontière
Marquez-la "use server" si elle doit s'exécuter sur le serveur, ou définissez-la dans le fichier client
Seuls des objets simples peuvent être passés aux Client Components
Des instances de classe, comme des modèles chargés de Date ou des Map, envoyées en props
Passez des données simples (chaînes, nombres, tableaux, objets simples)
window is not defined
API du navigateur utilisée pendant le rendu sur le serveur
Lisez-la dans useEffect, ou vérifiez d'abord typeof window
Erreur d'hydratation (hydration mismatch)
Le serveur et le navigateur ont rendu un texte différent (dates, valeurs aléatoires)
Affichez la partie variable uniquement côté client, ou transmettez la valeur depuis le serveur