Comment charger une donnée dynamique côté serveur
Dans cette leçon, on apprend à créer une route dynamique et à charger une donnée spécifique côté serveur avec React Router.
Débloquez cette leçon
Entrez votre email pour accéder gratuitement à ce contenu.
Dans cette leçon, tu vas apprendre à exploiter la méthode loader de React Router 7 pour récupérer des données dynamiques côté serveur, puis les injecter dans ton composant React. À la fin, tu sauras :
- Structurer ta logique « full-stack » en séparant le back-end et le front-end.
- Utiliser
loaderetuseLoaderDatapour un rendu SSR performant. - Organiser ton code avec un fichier
.server.tsqui n’est pas packagé côté client.
Pourquoi utiliser loader plutôt qu’un fetch client-side ?
En React classique, on place souvent un useEffect avec un fetch pour récupérer des données après le rendu initial. Cette approche :
- génère un flash d’état “loading” inutile,
- fait appel au réseau depuis le navigateur,
- ne profite pas du Server-Side Rendering (SSR) pour le SEO.
Avec React Router 7, chaque route peut exporter une fonction loader qui s’exécute :
- côté serveur lors du premier chargement (SSR),
- lors de la navigation client-side (via
<Link>ou<Form>).
Le résultat retourné par loader est directement injecté dans ton composant via le hook useLoaderData(). Le chargement est donc plus fluide, optimisé et sécurisé.
Créer un fichier de logique serveur
Par convention, on place la logique d’accès aux données dans un fichier suffixé .server.ts (ou .server.tsx). Ces fichiers ne sont jamais compilés côté client et contiennent par exemple la connexion à ta base de données ou un appel à un CMS.
1// Simule une base de données en mémoire2const db = {3users: [4{ id: 1, name: 'Virgile' },5{ id: 2, name: 'Robert' },6{ id: 3, name: 'John' },7{ id: 4, name: 'Jack' },8]9}1011// ^? Simulate db delay12export async function getUsers() {13// délai artificiel pour simuler un appel réel14await new Promise(resolve => setTimeout(resolve, 100))15return db.users16}
Tip
En production, remplace ce simulateur par un vrai client Prisma, Sequelize, ou un appel REST/GraphQL.
Déclarer la méthode loader dans la route
Maintenant, passons à notre route users.tsx. On importe getUsers() depuis le fichier .server.ts, puis on exporte une fonction loader qui récupère la liste des utilisateurs.
1import { useLoaderData } from 'react-router'2import type { LoaderFunctionArgs } from 'react-router'3import { getUsers } from '~/users.server'45export async function loader({}: LoaderFunctionArgs) {6// Exécute la requête serveur avant de rendre le composant7return { users: await getUsers() }8}910export default function UsersRoute() {11const { users } = useLoaderData<typeof loader>()12return (13<div className="px-8 py-4">14<h1 className="text-2xl font-bold">Utilisateurs</h1>15<ul>16{users.map(user => (17<li key={user.id} className="text-lg">18{user.name}19</li>20))}21</ul>22</div>23)24}
loaderretourne un objet{ users }.useLoaderData<typeof loader>()infère automatiquement le type renvoyé.
Loader vs component
La fonction loader s’exécute avant le rendu React, tandis que le composant React sert uniquement à afficher.
Organiser ton code full-stack
Grâce à cette séparation, ton bundle client reste léger : tout ce qui est dans *.server.ts n’est pas envoyé au navigateur. C’est à la fois une optimisation et une mesure de sécurité (pas de credentials exposés).
Structure du dossier
1app/2├── routes/3│ └── users.tsx # Composant et loader4└── users.server.ts # Logique server-side
Tester en local
- Lance ton serveur dev :
1npm run dev
- Va sur
http://localhost:5173/users
Tu devrais voir la liste des utilisateurs chargée sans flash de loading.
Tip
Utilise l’onglet « Network » pour vérifier que la page HTML contient déjà les données.
Aller plus loin
- Prochaine étape : Routes dynamiques pour afficher le profil de chaque utilisateur via un slug.
- Pour gérer les mutations (ajout/suppression), explore la méthode
actionet le composant<Form>. - Pense also à couvrir la gestion d’erreur avec un ErrorBoundary et la méthode
useCatch().
Exercices rapides
- Pagination simple
- Modifie
users.server.tspour exposergetUsers(page: number)qui slice 2 utilisateurs par page. - Ajoute deux liens “Précédent” / “Suivant” dans
UsersRoutepour naviguer entre?page=1,?page=2, etc.
- Modifie
- Gestion d’erreur
- Dans
loader, simule une erreur sipage > 3en lançantthrow new Response("Page introuvable", { status: 404 }). - Implémente un ErrorBoundary dans
root.tsxpour afficher un message personnalisé.
- Dans
- Chargement conditionnel
- Ajoute un paramètre de requête
?search=…. - Dans
loader, filtredb.usersparuser.name.includes(search). - Affiche un champ
<input>et un<button>pour soumettre le formulaire en GET. - Observe l’URL et le résultat sans JavaScript supplémentaire.
- Ajoute un paramètre de requête
Bonne exploration et à bientôt pour la suite du module !
Comprendre les concepts fondamentaux
Quelle est la principale différence entre les composants client et serveur dans React ?
Optimisation des performances
Quelle technique est recommandée pour éviter les rendus inutiles dans React ?
Architecture des données
Quel hook permet de gérer les effets de bord dans un composant React ?