Modèles React Router
SDK : @clerk/react-router v3+. Nécessite React Router v7.9+.
De Quoi Avez-Vous Besoin ?
| Tâche | Référence |
|---|---|
| Auth dans les loaders et actions | references/loaders-actions.md |
| Routes protégées et redirections | references/protected-routes.md |
| Données utilisateur SSR et session | references/ssr-auth.md |
Modèle Mental
React Router v7 utilise un pipeline middleware + loader. Clerk s'intègre aux deux niveaux :
- Middleware (
clerkMiddleware()) — s'exécute à chaque requête, attache l'auth au contexte rootAuthLoader— obligatoire dansroot.tsxpour passer l'état Clerk au clientgetAuth(args)— appelé dans n'importe quel loader/action pour obtenir l'utilisateur actuel
Request → clerkMiddleware() → rootAuthLoader → page loader → component
↓ ↓ ↓
attache l'auth injecte l'état getAuth(args)
au contexte à la réponse lit le contexte
Configuration Minimale
1. root.tsx
import { rootAuthLoader } from '@clerk/react-router/server'
import { ClerkApp } from '@clerk/react-router'
import type { Route } from './+types/root'
export async function loader(args: Route.LoaderArgs) {
return rootAuthLoader(args)
}
export default ClerkApp(function App() {
return <Outlet />
})
2. Middleware (root route ou entry.server.ts)
import { clerkMiddleware } from '@clerk/react-router/server'
export const middleware = [clerkMiddleware()]
Obligatoire :
rootAuthLoaderdoit être appelé dans le loader deroot.tsx. Sans cela,getAuthlève une erreur dans les loaders imbriqués.
Auth dans les Loaders
import { getAuth } from '@clerk/react-router/server'
import type { Route } from './+types/dashboard'
export async function loader(args: Route.LoaderArgs) {
const { userId } = await getAuth(args)
if (!userId) throw redirect('/sign-in')
const data = await fetchUserData(userId)
return { data }
}
Auth dans les Actions
import { getAuth } from '@clerk/react-router/server'
export async function action(args: Route.ActionArgs) {
const { userId, orgId } = await getAuth(args)
if (!userId) throw new Response('Unauthorized', { status: 401 })
const formData = await args.request.formData()
await saveData(userId, orgId, formData)
return redirect('/dashboard')
}
Composants Client
import { useAuth, useUser } from '@clerk/react-router'
export function Profile() {
const { userId, isSignedIn } = useAuth()
const { user } = useUser()
if (!isSignedIn) return null
return <p>{user?.firstName}</p>
}
Changement d'Organisation
import { OrganizationSwitcher } from '@clerk/react-router'
export function Nav() {
return <OrganizationSwitcher afterSelectOrganizationUrl="/dashboard" />
}
export async function loader(args: Route.LoaderArgs) {
const { userId, orgId } = await getAuth(args)
if (!userId) throw redirect('/sign-in')
if (!orgId) throw redirect('/select-org')
return { data: await fetchOrgData(orgId) }
}
Pièges Courants
| Symptôme | Cause | Solution |
|---|---|---|
clerkMiddleware() not detected |
Middleware manquant | Exportez middleware = [clerkMiddleware()] depuis la root route |
getAuth retourne un userId vide |
rootAuthLoader non appelé |
Appelez rootAuthLoader(args) dans le loader de root.tsx |
| Boucle de redirection infinie | La cible de redirection est aussi protégée | Excluez /sign-in de la vérification de protection |
redirect ne fonctionne pas dans action |
Utilisation de Response à la place de throw redirect() |
Utilisez throw redirect('/path') depuis react-router |
Tableau des Imports
| Quoi | Import Depuis |
|---|---|
getAuth |
@clerk/react-router/server |
rootAuthLoader |
@clerk/react-router/server |
clerkMiddleware |
@clerk/react-router/server |
ClerkApp |
@clerk/react-router |
useAuth, useUser |
@clerk/react-router |
OrganizationSwitcher |
@clerk/react-router |
Voir Aussi
clerk-setup- Installation initiale de Clerkclerk-custom-ui- Flux personnalisés et apparenceclerk-orgs- Organisations B2B