Créer un hook réutilisable pour récupérer l'utilisateur connecté

Apprends à centraliser la récupération de l’utilisateur connecté avec un hook React Router 7 simple et performant pour éviter les requêtes redondantes.

4 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%

Arrêter de dupliquer le loader

Chaque fois que tu veux connaître l’utilisateur connecté, tu appelles la même fonction dans le loader de la route courante ?

app/routes/index.tsx
1
export async function loader({ request }: LoaderArgs) {
2
return { user: await getOptionalUser({ request }) }
3
}

Ça marche, mais :

  1. la requête part trois fois si ta page empile trois routes imbriquées ;
  2. tu termines avec autant de loader copiés/collés que de pages.

On peut faire mieux : charger l’utilisateur une seule fois dans root.tsx, puis l’exposer partout via un hook maison.


Le plan en trois étapes

  1. Charger l’utilisateur dans le loader de app/root.tsx.
  2. Lire cette data depuis n’importe quelle route avec useRouteLoaderData().
  3. Envelopper le tout dans useOptionalUser() pour une API ultra-simple.

1 – Charger l’utilisateur à la racine

app/root.tsx
1
import { data, type LoaderFunctionArgs } from "react-router"
2
import { getOptionalUser } from "~/server/sessions.server"
3
4
export async function loader({ request }: LoaderFunctionArgs) {
5
const user = await getOptionalUser({ request }) // ↙︎ DB + cookie
6
return data({ user }) // { user | null }
7
}

La route root est toujours montée, donc ce loader tourne exactement une fois par navigation.


2 – Récupérer la data via useRouteLoaderData

react-router expose un hook miracle :

1
useRouteLoaderData<typeof rootLoader>("root")
  • root = l’ID de la route ciblée
  • le type générique reprend celui du loader ⇒ aucune conversion manuelle

3 – Emballer tout ça dans un hook réutilisable

app/root.tsx
1
import { useRouteLoaderData } from "react-router"
2
import type { loader as rootLoader } from "./root.tsx"
3
4
export function useOptionalUser() {
5
const data = useRouteLoaderData<typeof rootLoader>("root")
6
return data?.user ?? null // 👈 renvoie User | null
7
}

Et voilà ! Tu viens de créer un « contexte » sans React.createContext, sans useState, sans provider. React Router se charge de la distribution.


Utilisation dans n’importe quelle page

app/routes/index.tsx
1
import { useOptionalUser } from "~/root"
2
3
export default function Home() {
4
const user = useOptionalUser()
5
6
return (
7
<h1 className="text-2xl font-bold">
8
{user ? `Salut ${user.firstName}` : "Bienvenue 👋"}
9
</h1>
10
)
11
}

Aucun loader, zéro requête : le composant lit directement la donnée déjà chargée.


Zoom : comment React Router propage les données ?

  1. Au premier rendu SSR ou lors d’une navigation, React Router exécute tous les loader des routes actives (root → layout → page).
  2. Les résultats sont stockés dans un cache interne.
  3. useRouteLoaderData() lit simplement ce cache.

Résultat : même si trois composants lisent useOptionalUser(), l’appel base de données ne part qu’une fois.


Et si je veux partager une donnée dans un layout ?

Répète exactement la même stratégie !

app/routes/users+/_usersLayout.tsx
1
export async function loader() {
2
return { users: await getUsers() }
3
}
4
5
export function useUsersData() {
6
const data = useRouteLoaderData<typeof loader>("routes/users+/_usersLayout")
7
if (!data) throw new Error("useUsersData must be used inside UsersLayout")
8
return data.users
9
}

Toutes les routes enfants (/users, /users/:slug, …) peuvent alors appeler useUsersData() sans re-requêter la DB.


Gérer le cas « hook utilisé hors contexte »

Hors du layout, useRouteLoaderData() renvoie undefined. Deux options :

  1. Tolérant : return data?.users ?? []
  2. Strict : if (!data) throw new Error("…") Tu seras immédiatement averti si tu importes le hook au mauvais endroit.

Bonus : un hook TypeScript-friendly

Pour éviter de retaper le nom de la route, déclare l’ID en variable :

app/root.tsx
1
export const ROOT_ID = "root"
2
3
export async function loader() { … }
4
5
export function useOptionalUser() {
6
return useRouteLoaderData<typeof loader>(ROOT_ID)?.user ?? null
7
}

Si tu renommes ta route, un simple Find & Replace suffira.


Points clés à retenir

  • Charge à la racine, lis partout : un seul hit DB pour toute l’appli.
  • useRouteLoaderData() lit la data d’une route précise ; tu peux l’utiliser à n’importe quelle profondeur.
  • Un hook custom rend l’API lisible (useOptionalUser()) et garde un typage strict (User | null).
  • Plus besoin de React.Context pour diffuser des données chargées côté serveur.
  • Pour les données relatives à un sous-layout, crée un second hook useXXXData() sur le même modèle
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