Amélioration de l'expérience administrateur : UI / UX avec ErrorBoundary, 404 et dashboard

Apprends à offrir une UX admin SaaS avec React Router 7: ErrorBoundary dédié, routes catch-all, sidebar active et dashboard synthétique. Level up dev.

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
72 leçons
Accès à vie
299.49
-35%

Objectif : offrir une UX admin digne d’un SaaS

Jusqu’ici l’admin tombait :

  • sur une page d’accueil vide,
  • sur des routes incomplètes (pas de 404 contextualisée, sidebar absente en cas d’erreur),
  • sur des menus qui ne reflétaient plus la structure réelle (Users vs Customers).

Dans cette itération nous :

  1. ajoutons un ErrorBoundary dédié au layout admin ;
  2. créons une route catch-all pour les URLs inconnues côté admin et public ;
  3. fusionnons les pages Customers / Users et simplifions la navigation ;
  4. indiquons le lien actif dans la sidebar ;
  5. mettons en place un dashboard synthétique, plus un bouton Logout.

1 ErrorBoundary spécifique au back-office

Pourquoi ? Conserver la sidebar même lorsqu’une route interne lève une erreur.

app/routes/admin+/_adminLayout.tsx
1
export function ErrorBoundary() {
2
return (
3
<SidebarProvider>
4
<AdminSidebar /> // ✅ sidebar toujours visible
5
<SidebarInset>
6
<header className="flex h-16 items-center gap-2 border-b px-4">
7
<SidebarTrigger className="-ml-1" />
8
<h1 className="text-xl font-semibold text-destructive">
9
Administration – Erreur
10
</h1>
11
</header>
12
<div className="flex flex-1 flex-col gap-4 p-4">
13
<GeneralErrorBoundary
14
defaultStatusHandler={({ error }) => (
15
<AdminErrorCard error={error} /> // composant décrit plus bas
16
)}
17
/* statusHandlers 404, 403, fallback … */
18
/>
19
</div>
20
</SidebarInset>
21
</SidebarProvider>
22
)
23
}

Explication

  • On enveloppe l’ancien GeneralErrorBoundary pour garder la navigation latérale.
  • Les statusHandlers personnalisent le rendu (404 → liens utiles, 403 → message d’accès refusé, etc.).

2 Route catch-all admin

Objectif : intercepter toute URL inconnue sous /admin/* et afficher un message contextuel.

app/routes/admin+/$ .tsx
1
export async function loader({ request }: Route.LoaderArgs) {
2
await requireAdmin(request) // sécurité = encore obligatoire
3
throw data("Page d'administration introuvable", { status: 404 })
4
}
5
6
export function ErrorBoundary() {
7
return <AdminNotFound /> // carte 404 illustrée
8
}
  • $.tsx (« dollar » dans le file-based routing) = catch-all.
  • On réutilise le composant AdminNotFound (liens rapides vers produits, users…).

3 Route catch-all publique

Même principe côté front pour conserver <Navbar /> et <Footer /> en cas d’erreur :

app/routes/$ .tsx
1
export function ErrorBoundary() {
2
return <PublicNotFound /> // 404 full-width + CTA
3
}

4 Fusion Users + Customers

L’ancienne arborescence :

1
/admin/users – Users (admin)
2
/admin/customers – Customers (doublon)

Action réalisée :

  1. suppression du dossier customers+;
  2. renommage de users+/index.tsx en users+/index.tsx (mais affichant désormais la liste clients) ;
  3. le layout intermédiaire (ancien users+/_layout) a été supprimé ; on ouvre la page détail dans un nouvel onglet pour un écran « plein » plus lisible.

Effet immédiat : moins de redirections, URL plus courtes : /admin/users/:userId.


5 Lien actif dans la sidebar

app/routes/admin+/_adminLayout.tsx {36-50}
1
const isActive = location.pathname.startsWith(link.to)
2
3
<SidebarMenuButton asChild isActive={isActive}>
4
<Link to={link.to}>
5
<IconComponent className="size-4" />
6
<span>{link.label}</span>
7
</Link>
8
</SidebarMenuButton>
  • Sur mobile comme desktop, le segment actif est mis en surbrillance.
  • startsWith couvre aussi les routes imbriquées (/admin/users/123 active /admin/users).

6 Dashboard synthétique

app/routes/admin+/dashboard.tsx
1
export async function loader({ request }) {
2
await requireAdmin(request)
3
const stats = await getDashboardStats() // Prisma + agrégations
4
return { stats }
5
}
{20-34} app/routes/admin+/dashboard.tsx
1
<div className="grid gap-4 md:grid-cols-4">
2
<KpiCard title="Total utilisateurs" icon={Users} value={stats.totals.users} />
3
<KpiCard title="Total produits" icon={Package} value={stats.totals.products} />
4
<KpiCard title="Total commandes" icon={ShoppingCart} value={stats.totals.orders} />
5
<KpiCard title="Chiffre d'affaires" icon={Euro} value={`${stats.totals.revenue.toLocaleString('fr-FR')}€`} />
6
</div>

getDashboardStats() calcule :

  • totals.users, products, orders, revenue ;
  • ordersByStatus (PENDING, PAID, FULFILLED) ;
  • recentOrders (5 dernières) ;
  • recentUsers.

7 Bouton Logout interne à l’admin

app/routes/admin+/_adminLayout.tsx {67-75}
1
<SidebarMenuItem>
2
<SidebarMenuButton onClick={handleSignOut} className="text-red-600">
3
<LogOut className="size-4" />
4
<span>Déconnexion</span>
5
</SidebarMenuButton>
6
</SidebarMenuItem>

handleSignOut appelle signOut() fourni par Better Auth, puis redirige vers /.


8 Résultat

  • page 404 admin et publique gardent leurs layouts respectifs ;
  • liste clients unifiée, fiche détail plein écran + sessions actives ;
  • dashboard synthétique visible au premier coup d’œil ;
  • sidebar toujours lisible et active ;
  • UX admin fluide : aucune page blanche, navigation plus claire.

9 À retenir

  1. ErrorBoundary local → garde la navigation en cas de panne.
  2. Route catch-all dans chaque layout pour éviter les 404 globales.
  3. Fusionner les pages réduit la dette UI et le nombre de liens.
  4. Lien actif : un feedback visuel très simple améliore grandement l’orientation.
  5. Un tableau de bord condensé vaut mieux qu’une page blanche.

10 Commit final

1
git checkout -b 7-15-amelioration-experience-admin
2
git add .
3
git commit -m "feat(admin): UX améliorée (ErrorBoundary, 404, sidebar active, dashboard)"
4
git push -u origin 7-15-amelioration-experience-admin

Ta branche est prête pour la PR – la CI passera sans toucher au backend 🚀

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