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.
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é
Chaque fois que tu veux connaître l’utilisateur connecté, tu appelles la
même fonction dans le loader
de la route courante ?
1export async function loader({ request }: LoaderArgs) {2return { user: await getOptionalUser({ request }) }3}
Ça marche, mais :
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.
loader
de app/root.tsx
.useRouteLoaderData()
.useOptionalUser()
pour une API ultra-simple.1import { data, type LoaderFunctionArgs } from "react-router"2import { getOptionalUser } from "~/server/sessions.server"34export async function loader({ request }: LoaderFunctionArgs) {5const user = await getOptionalUser({ request }) // ↙︎ DB + cookie6return data({ user }) // { user | null }7}
La route root
est toujours montée, donc ce loader tourne exactement
une fois par navigation.
useRouteLoaderData
react-router
expose un hook miracle :
1useRouteLoaderData<typeof rootLoader>("root")
root
= l’ID de la route cibléeloader
⇒ aucune conversion manuelle1import { useRouteLoaderData } from "react-router"2import type { loader as rootLoader } from "./root.tsx"34export function useOptionalUser() {5const data = useRouteLoaderData<typeof rootLoader>("root")6return data?.user ?? null // 👈 renvoie User | null7}
Et voilà !
Tu viens de créer un « contexte » sans React.createContext
, sans
useState
, sans provider. React Router se charge de la distribution.
1import { useOptionalUser } from "~/root"23export default function Home() {4const user = useOptionalUser()56return (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.
loader
des routes actives (root → layout → page).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.
Répète exactement la même stratégie !
1export async function loader() {2return { users: await getUsers() }3}45export function useUsersData() {6const data = useRouteLoaderData<typeof loader>("routes/users+/_usersLayout")7if (!data) throw new Error("useUsersData must be used inside UsersLayout")8return data.users9}
Toutes les routes enfants (/users
, /users/:slug
, …) peuvent alors
appeler useUsersData()
sans re-requêter la DB.
Hors du layout, useRouteLoaderData()
renvoie undefined
.
Deux options :
return data?.users ?? []
if (!data) throw new Error("…")
Tu seras immédiatement averti si tu importes le hook au mauvais endroit.Pour éviter de retaper le nom de la route, déclare l’ID en variable :
1export const ROOT_ID = "root"23export async function loader() { … }45export function useOptionalUser() {6return useRouteLoaderData<typeof loader>(ROOT_ID)?.user ?? null7}
Si tu renommes ta route, un simple Find & Replace
suffira.
useRouteLoaderData()
lit la data d’une route précise ; tu peux
l’utiliser à n’importe quelle profondeur.useOptionalUser()
) et garde
un typage strict (User | null
).React.Context
pour diffuser des données chargées
côté serveur.useXXXData()
sur le même modèleQuelle 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 ?