Dans cette leçon on va apprendre à combiner client loader, action, hydrateFallback, Suspense et revalidate pour une UX rapide et cache SSR/SPA.
avec React Router 7
Posez vos questions 24/7 à notre IA experte en React Router 7
Validez vos acquis avec des quiz personnalisés et un feedback instantané
Dans React Router 7, le chargement client permet de récupérer des données après l’hydratation initiale, sans recharger toute la page ni retomber dans un rendu serveur (SSR). Tu utilises :
export async function clientLoader
dans tes modules de routeuseLoaderData
pour accéder à la promesse renvoyée<Suspense>
et <Await>
pour afficher un squelette avant le renduCette approche améliore l’expérience utilisateur (UX) en évitant le flash de chargement et en accélérant la navigation.
clientLoader
Comme le loader
côté serveur, le clientLoader
est une fonction exportée depuis un module de route. Elle :
serverLoader
.{ users: User[] }
.1import { useLoaderData } from "react-router"23// 1. loader serveur : renvoie une promesse4export async function loader() {5return { usersPromise: getUsers() } // getUsers() -> Promise<User[]>6}78// 2. Hydratation initiale : on stocke la donnée côté client9export async function clientLoader({ serverLoader }) {10console.log("trigger client loader")11const { usersPromise } = await serverLoader()12return { users: await usersPromise }13}
clientLoader.hydrate = true
indique à React RouterclientLoader
dès l’hydratation, sans attendre la navigation.<Suspense>
et <Await>
Pour exploiter la promesse côté client, tu combines :
<Suspense fallback={…}>
: affiche le squelette tant que la promesse n’est pas résolue.<Await resolve={promise}>
: récupère et injecte la donnée dans ton JSX.1import { Suspense } from "react"2import { Await, useLoaderData } from "react-router"34export default function Users() {5// Promise<User[]>6const { usersPromise } = useLoaderData<typeof loader>()78return (9<div className="px-8 py-2">10<h1 className="text-2xl font-bold">Utilisateurs</h1>1112<Suspense13fallback={14<ul>15<li className="h-6 w-3/4 bg-gray-300 rounded animate-pulse mb-2" />16<li className="h-6 w-2/3 bg-gray-300 rounded animate-pulse mb-2" />17<li className="h-6 w-4/5 bg-gray-300 rounded animate-pulse mb-2" />18<li className="h-6 w-3/5 bg-gray-300 rounded animate-pulse" />19</ul>20}21>22<Await resolve={usersPromise}>23{(users) => (24<ul>25{users.map((user) => (26<li key={user.id} className="text-lg font-mono">27{user.name}28</li>29))}30</ul>31)}32</Await>33</Suspense>34</div>35)36}
Le composant fallback s’affiche instantanément côté client,
sans attendre le second rendu hydraté.
shouldRevalidate
Par défaut, chaque navigation relance le loader
et le clientLoader
.
Pour désactiver ce comportement, tu peux exporter :
1export function shouldRevalidate({ nextLocation, formMethod }) {2// Toujours false ⇒ pas de rechargement automatique3return false4}
1export function shouldRevalidate(arg) {2- return true3+ return false4}
Utile pour les données statiques ou déjà mises en cache par le serveur.
clientLoader
complète le loader
SSR pour charger après l’hydratation.<Suspense>
+ <Await>
affichent un squelette pendant le chargement client.clientLoader.hydrate = true
déclenche dès l’hydratation initiale.useLoaderData<typeof loader>()
fournit la promesse côté client.shouldRevalidate
te permet de stabiliser ou forcer la ré-exécution.Pagination simple
getUsers()
pour accepter page: number
.clientLoader
avec le paramètre ?page=…
et afficheGestion d’erreur client-side
usersPromise
, lance une exception pourpage > 3
.<ErrorBoundary>
.Skeleton avancé
<UserSkeleton />
réutilisable.Quelle est la principale différence entre les composants client et serveur dans React ?
Quelle technique est recommandée pour éviter les rendus inutiles dans React ?
Quel hook permet de gérer les effets de bord dans un composant React ?
Comment implémenter la gestion des erreurs pour les requêtes API dans React ?
Quelle est la meilleure pratique pour déployer une application React en production ?