# Patterns front-end validés Ce fichier contient **uniquement** des patterns front-end : - testés, - validés, - utilisés dans des projets réels (ou des apps complètes, pas des snippets isolés). Il sert de **mémoire durable** pour éviter : - de refaire les mêmes erreurs, - de redélibérer éternellement sur des sujets déjà tranchés, - de propager des “bonnes pratiques” théoriques non éprouvées. Dernière mise à jour : 25-01-2026 --- ## Règle d’or Si ce n’est pas **confirmé comme fonctionnel et utile**, **ça n’a rien à faire ici**. - Pas de conseils vagues - Pas de patterns “à la mode” - Pas de dépendance implicite à un framework ou une version non précisée --- ## Périmètre couvert - SPA et webapps - UX technique (forms, erreurs, loading, feedback) - State management (client / server) - Architecture front-end - Performance et accessibilité - Sécurité front (au niveau applicatif) - DX et maintenabilité Ce fichier traite le **front-end comme un logiciel en production**, au même niveau d’exigence que le backend. --- ## Format standard d’un pattern (obligatoire) ## Pattern : - Objectif : ce que le pattern résout - Contexte : type d’application / contraintes - Quand l’utiliser : cas pertinents - Quand l’éviter : contre-exemples - Avantages : bénéfices concrets - Limites / vigilance : pièges, dette potentielle - Validé le : DD-MM-YYYY - Contexte technique : framework + version + tooling principal ### Implémentation (exemple minimal) ```txt (contenu volontairement minimal, lisible, non-magique) ``` --- ## Pattern : Gestion explicite des états UI (loading / empty / error) ### Synthèse - **Objectif** : éviter les interfaces ambiguës ou incohérentes en rendant explicites tous les états possibles d’une vue. - **Contexte** : SPA ou webapp consommant des données asynchrones (API, backend, cache). - **Quand l’utiliser** : dès qu’une vue dépend de données externes ou d’un traitement async. - **Quand l’éviter** : vues purement statiques ou synchrones sans dépendance externe. ### Analyse - **Avantages** : - UX plus prévisible et compréhensible - Debug facilité (état visible = problème identifiable) - Base saine pour tests et accessibilité - **Limites / vigilance** : - Peut sembler verbeux sur des écrans simples - Nécessite une discipline pour ne pas “court-circuiter” les états ### Validation - Validé le : 25-01-2026 - Contexte technique : SPA (React / Vue / Svelte agnostique), API HTTP ### Implémentation (exemple minimal) ```txt if (loading) { afficher un skeleton ou spinner } else if (error) { afficher un message clair + action possible } else if (data est vide) { afficher un état empty explicite } else { afficher la vue nominale } ``` ### Checklist - [ ] Aucun écran blanc ou silencieux - [ ] Message d’erreur compréhensible pour l’utilisateur - [ ] États testables individuellement - [ ] Accessibilité respectée (focus, lecture écran) - [ ] Pas de logique métier cachée dans le rendu --- ## Pattern : Séparation claire server state / client state ### Synthèse - **Objectif** : éviter le mélange des responsabilités entre données serveur et état local UI. - **Contexte** : SPA ou webapp consommant une API avec interactions utilisateur. - **Quand l’utiliser** : dès que l’application affiche des données distantes modifiables ou synchronisées. - **Quand l’éviter** : applications très simples ou purement statiques. ### Analyse - **Avantages** : - Logique plus lisible et testable - Réduction des bugs liés aux états incohérents - Évolutivité facilitée quand l’app grossit - **Limites / vigilance** : - Demande de la rigueur dans le découpage - Peut sembler abstrait au début pour des petits projets ### Validation - Validé le : 25-01-2026 - Contexte technique : SPA agnostique (React / Vue / Svelte), API HTTP ### Implémentation (exemple minimal) ```txt serverState = données venant du backend (fetch, cache, sync) clientState = état local UI (filtres, onglets, modales, formulaires) Ne jamais : - stocker du state UI dans le cache serveur - dériver la logique UI directement des réponses API sans adaptation ``` ### Checklist - [ ] Les données serveur peuvent être invalidées / rechargées - [ ] L’état UI est local et réinitialisable - [ ] Les responsabilités sont lisibles dans le code - [ ] Les tests peuvent cibler chaque type d’état - [ ] Pas de dépendance implicite entre UI et API --- ## Pattern : Formulaire robuste avec validation et erreurs explicites ### Synthèse - **Objectif** : garantir des formulaires fiables, compréhensibles et maintenables. - **Contexte** : toute interface avec saisie utilisateur et règles métier. - **Quand l’utiliser** : dès qu’un formulaire dépasse un simple champ isolé. - **Quand l’éviter** : formulaires ultra-simples sans validation réelle. ### Analyse - **Avantages** : - UX claire (l’utilisateur sait quoi corriger) - Moins d’erreurs silencieuses - Base saine pour tests et accessibilité - **Limites / vigilance** : - Peut sembler verbeux sans discipline - Risque de duplication si mal factorisé ### Validation - Validé le : 25-01-2026 - Contexte technique : Front-end agnostique, API HTTP ### Implémentation (exemple minimal) ```txt - Validation côté client (format, champs requis) - Validation côté serveur (règles métier) - Mapping explicite des erreurs serveur → champs UI - Aucun submit silencieux ``` ### Checklist - [ ] Messages d’erreur compréhensibles et localisés - [ ] Validation client + serveur cohérente - [ ] Focus automatique sur le champ en erreur - [ ] États loading / disabled gérés - [ ] Tests sur cas valides et invalides --- ## Pattern : Navigation réactive post-action async (React / Expo Router) ### Synthèse - **Objectif** : déclencher la navigation après une action asynchrone (login, register, submit) de façon idiomatique et sans bypasser la réactivité React. - **Contexte** : SPA ou app mobile React avec state management (Zustand, Redux, Context) et router déclaratif (React Router, Expo Router, Next.js App Router). - **Quand l'utiliser** : dès qu'une navigation dépend du résultat d'une action async. - **Quand l'éviter** : navigations synchrones sans état async impliqué. ### Analyse - **Avantages** : - Respecte le cycle de vie React (pas de lecture de state hors cycle) - Re-render automatique si l'état change entre-temps - Testable : on peut assert sur l'état, pas sur des effets de bord - **Limites / vigilance** : - Ne pas oublier les dépendances du `useEffect` (ESLint react-hooks/exhaustive-deps) - Gérer le cas "composant démonté" si la navigation peut être annulée ### Validation - Validé le : 07-03-2026 - Contexte technique : React 18+ / Zustand / Expo Router — pattern applicable sur React Router, Next.js App Router ### Implémentation (exemple minimal) ```typescript // ❌ Anti-pattern : lecture de state hors cycle React const handleSubmit = async () => { await login(email, password); const { accessToken } = useAuthStore.getState(); // bypasse la réactivité if (accessToken) router.replace('/(tabs)'); }; // ✅ Pattern correct : useEffect réactif sur le state const { accessToken, isLoading, error } = useAuthStore(); useEffect(() => { if (accessToken && !isLoading && !error) { router.replace('/(tabs)'); } }, [accessToken, isLoading, error]); const handleSubmit = async () => { await login(email, password); // la navigation se déclenche via useEffect quand le store se met à jour }; ``` ### Pour les callbacks OAuth (ref nécessaire) ```typescript // Quand un callback externe déclenche la navigation const pendingOAuth = useRef(false); useEffect(() => { if (pendingOAuth.current && accessToken) { pendingOAuth.current = false; router.replace('/(tabs)'); } }, [accessToken]); const handleOAuth = async () => { pendingOAuth.current = true; await exchangeWithIdp(token); }; ``` ### Checklist - [ ] Aucun `store.getState()` utilisé pour lire l'état post-action dans un handler - [ ] `useEffect` avec dépendances explicites (state pertinent + isLoading + error) - [ ] Cas d'erreur géré (ne pas naviguer si error est défini) - [ ] `useRef` si le trigger vient d'un callback externe (OAuth, deep link) --- ### Index des patterns - Gestion explicite des états UI (loading / empty / error) - Séparation claire server state / client state - Formulaire robuste avec validation et erreurs explicites - Navigation réactive post-action async (React / Expo Router) ⸻ ### Principes transverses - Un pattern = une responsabilité claire - On privilégie la simplicité locale avant la généricité globale - Le code doit rester compréhensible 6 mois plus tard - Si un pattern devient central → il mérite une décision d’architecture dédiée ⸻ ## Notes importantes - 3 bons patterns > 30 moyens - Si un pattern évolue : - on met à jour la date - on précise le nouveau contexte - En cas de doute → le pattern n’entre pas encore ici