Comment charger une donnée dynamique côté client

Dans cette leçon on va apprendre à combiner client loader, action, hydrateFallback, Suspense et revalidate pour une UX rapide et cache SSR/SPA.

3 min read
Déverrouillez votre potentiel

avec React Router 7

Vous en avez marre de...

❌ perdre du temps à chercher des informations éparpillées
❌ ne pas avoir de retour sur votre progression
Assistant IA spécialisé

Posez vos questions 24/7 à notre IA experte en React Router 7

Quiz interactifs

Validez vos acquis avec des quiz personnalisés et un feedback instantané

9 modules
45 leçons
Accès à vie
299.00
-50%

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 route
  • le hook useLoaderData pour accéder à la promesse renvoyée
  • <Suspense> et <Await> pour afficher un squelette avant le rendu

Cette approche améliore l’expérience utilisateur (UX) en évitant le flash de chargement et en accélérant la navigation.


Principe du clientLoader

Comme le loader côté serveur, le clientLoader est une fonction exportée depuis un module de route. Elle :

  1. Récupère une promesse fournie par le serverLoader.
  2. Peut mettre en cache la donnée côté client.
  3. Renvoie un objet { users: User[] }.
app/routes/users.tsx
1
import { useLoaderData } from "react-router"
2
3
// 1. loader serveur : renvoie une promesse
4
export async function loader() {
5
return { usersPromise: getUsers() } // getUsers() -> Promise<User[]>
6
}
7
8
// 2. Hydratation initiale : on stocke la donnée côté client
9
export async function clientLoader({ serverLoader }) {
10
console.log("trigger client loader")
11
const { usersPromise } = await serverLoader()
12
return { users: await usersPromise }
13
}

Rendu avec <Suspense> et <Await>

Pour exploiter la promesse côté client, tu combines :

  1. Un <Suspense fallback={…}> : affiche le squelette tant que la promesse n’est pas résolue.
  2. Un <Await resolve={promise}> : récupère et injecte la donnée dans ton JSX.
app/routes/users.tsx
1
import { Suspense } from "react"
2
import { Await, useLoaderData } from "react-router"
3
4
export default function Users() {
5
// Promise<User[]>
6
const { usersPromise } = useLoaderData<typeof loader>()
7
8
return (
9
<div className="px-8 py-2">
10
<h1 className="text-2xl font-bold">Utilisateurs</h1>
11
12
<Suspense
13
fallback={
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
}

Contrôler la révalidation avec shouldRevalidate

Par défaut, chaque navigation relance le loader et le clientLoader.
Pour désactiver ce comportement, tu peux exporter :

app/routes/users.tsx
1
export function shouldRevalidate({ nextLocation, formMethod }) {
2
// Toujours false ⇒ pas de rechargement automatique
3
return false
4
}
src/routes/users.tsx
1
export function shouldRevalidate(arg) {
2
- return true
3
+ return false
4
}

Points clés

  • 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.

Exercices rapides

  1. Pagination simple

    • Modifie getUsers() pour accepter page: number.
    • Appelle clientLoader avec le paramètre ?page=… et affiche
      “Précédent / Suivant”.
  2. Gestion d’erreur client-side

    • Dans usersPromise, lance une exception pour
      page > 3.
    • Affiche un message d’erreur personnalisé avec <ErrorBoundary>.
  3. Skeleton avancé

    • Crée un composant <UserSkeleton /> réutilisable.
    • Affiche 5 squelettes au lieu de 4 pendant le fallback.
Premium
Quiz interactif
Testez vos connaissances et validez votre compréhension du module avec notre quiz interactif.
1

Comprendre les concepts fondamentaux

Quelle est la principale différence entre les composants client et serveur dans React ?

Les composants client s'exécutent uniquement dans le navigateur
Les composants serveur peuvent utiliser useState
Les composants client sont plus rapides
Il n'y a aucune différence significative
2

Optimisation des performances

Quelle technique est recommandée pour éviter les rendus inutiles dans React ?

Utiliser React.memo pour les composants fonctionnels
Ajouter plus d'états locaux
Éviter d'utiliser les props
Toujours utiliser les class components
3

Architecture des données

Quel hook permet de gérer les effets de bord dans un composant React ?

useEffect
useState
useMemo
useContext
4

Gestion des erreurs

Comment implémenter la gestion des erreurs pour les requêtes API dans React ?

Utiliser try/catch avec async/await
Ignorer les erreurs
Toujours afficher un message d'erreur
Rediriger l'utilisateur
5

Déploiement et CI/CD

Quelle est la meilleure pratique pour déployer une application React en production ?

Utiliser un service CI/CD comme GitHub Actions
Copier les fichiers manuellement via FTP
Envoyer le code source complet
Ne jamais mettre à jour l'application

Débloquez ce quiz et tous les autres contenus premium en achetant ce cours