Récupérer l'utilisateur connecté depuis les cookies

Apprends à gérer la session utilisateur avec React Router 7 en récupérant l’id depuis les cookies pour sécuriser et personnaliser tes routes facilement.

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%

Une fois ton formulaire de connexion validé, React Router 7 place l’id de l’utilisateur dans un cookie de session. Notre objectif dans cette leçon : retrouver cet id à chaque requête, charger l’utilisateur en base et exposer ces infos, côté serveur comme côté client, via un helper ultra-simple : getOptionalUser().


1. Poser la fondation : la session React Router

React Router fournit la factory createCookieSessionStorage() (alias CSSS) qui lit, signe et détruit tes cookies pour toi. Crée un fichier dédié :

app/server/sessions.server.ts
1
import { createCookieSessionStorage } from "react-router"
2
3
type SessionData = { userId: string }
4
type SessionFlashData = { error: string }
5
6
const { getSession, commitSession, destroySession } =
7
createCookieSessionStorage<SessionData, SessionFlashData>({
8
cookie: {
9
name: "__session",
10
sameSite: "lax",
11
httpOnly: true,
12
path: "/",
13
secrets: [process.env.SESSION_SECRET!], // 🔐
14
secure: process.env.NODE_ENV === "production",
15
},
16
})
17
18
export { getSession, commitSession, destroySession }

Ici on ne stocke qu’une seule clé (userId). Si tu as aussi un thème ou une langue, crée d’autres cookies – mêler tout dans la même session complique la vie (lecture sur chaque route, invalidation, etc.).


2. Stocker l’id au moment du login

Dans l’action de ta route /login tu reçois l’utilisateur (ex. via Prisma), puis tu places son id dans la session :

app/routes/login.tsx
1
import { commitSession, getSession } from "~/server/sessions.server"
2
3
export async function action({ request }: ActionFunctionArgs) {
4
const form = await request.formData()
5
const user = await prisma.user.findUnique({
6
where: { email: form.get("email") as string },
7
})
8
/* … vérification mot de passe … */
9
10
const session = await getSession(request.headers.get("Cookie"))
11
session.set("userId", String(user.id))
12
13
return redirect("/", {
14
headers: { "Set-Cookie": await commitSession(session) },
15
})
16
}

Le cookie signé est envoyé dans le header Set-Cookie. À la requête suivante, il arrivera automatiquement dans request.headers.get("Cookie").


3. Centraliser la lecture des cookies

Plutôt que de copier/coller getSession partout, ajoutons deux helpers :

app/server/sessions.server.ts
1
// …
2
3
export async function getUserId({ request }: { request: Request }) {
4
const session = await getSession(request.headers.get("Cookie"))
5
return session.get("userId") as string | undefined
6
}
7
8
export async function getOptionalUser({ request }: { request: Request }) {
9
const userId = await getUserId({ request })
10
if (!userId) return null
11
12
// ⚠️ le cookie peut être forgé : on vérifie qu’il existe vraiment
13
return prisma.user.findUnique({
14
where: { id: Number(userId) },
15
select: { id: true, firstName: true, lastName: true },
16
})
17
}

Pourquoi « optional » ? La fonction peut renvoyer null : un visiteur anonyme n’est pas une erreur.


4. Protéger / rediriger les routes

a. Empêcher un utilisateur connecté d’accéder à /login :

{3,8-12} app/routes/login.tsx
1
import { getOptionalUser } from "~/server/sessions.server"
2
3
export async function loader({ request }: LoaderFunctionArgs) {
4
const user = await getOptionalUser({ request })
5
if (user) return redirect("/") // déjà loggé → retour home
6
return null
7
}

b. Afficher l’utilisateur dans le loader de la racine :

app/root.tsx
1
export async function loader({ request }: LoaderFunctionArgs) {
2
const user = await getOptionalUser({ request })
3
return data({ user })
4
}

Côté client :

app/root.tsx {18-26}
1
const { user } = useLoaderData<typeof loader>()
2
3
<header>
4
{/* … */}
5
{user ? (
6
<Form method="POST" action={href("/logout")}>
7
<button type="submit">Logout</button>
8
</Form>
9
) : (
10
<Link to={href("/login")}>Login</Link>
11
)}
12
</header>

5. Implémenter la route /logout

Un simple POST détruit la session puis redirige :

app/routes/logout.tsx
1
import { destroySession, getSession } from "~/server/sessions.server"
2
3
export async function action({ request }: ActionFunctionArgs) {
4
const session = await getSession(request.headers.get("Cookie"))
5
return redirect("/", {
6
headers: { "Set-Cookie": await destroySession(session) },
7
})
8
}

6. Refactor final – le code devient lisible

Les loaders utilisent une ligne pour récupérer l’utilisateur, les actions n’ont plus qu’à écrire :

1
const id = await getUserId({ request })
2
if (!id) throw redirect("/login")

Lisibilité + sécurité = ❤️


Points clés à retenir

  • createCookieSessionStorage() gère la lecture/écriture/suppression du cookie.
  • Un helper getUserId() puis getOptionalUser() suppriment la duplication et vérifient que le cookie pointe vers un vrai user.
  • Les loaders deviennent l’endroit idéal pour :
    1. protéger un écran (rediriger si pas connecté) ;
    2. injecter l’utilisateur dans l’UI.
  • Une simple route resource /logout détruit la session.
  • Garde chaque préference (thème, langue, etc.) dans son cookie dédié : plus simple à maintenir, plus sûr.
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