Files
_Assistant_Lead_Tech/10_frontend_patterns_valides.md
2026-03-09 10:28:02 +01:00

309 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 : 09-03-2026
---
## Index
- [Gestion explicite des états UI (loading / empty / error)](#pattern-etats-ui-loading-empty-error)
- [Séparation claire server state / client state](#pattern-separation-server-state-client-state)
- [Formulaire robuste avec validation et erreurs explicites](#pattern-formulaire-robuste)
- [Navigation réactive post-action async (React / Expo Router)](#pattern-navigation-reactive-post-action-async)
---
## Règle dor
Si ce nest pas **confirmé comme fonctionnel et utile**,
**ça na 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 dexigence que le backend.
---
## Format standard dun pattern (obligatoire)
## Pattern : <Nom clair et précis>
- Objectif : ce que le pattern résout
- Contexte : type dapplication / contraintes
- Quand lutiliser : 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)
```
---
<a id="pattern-etats-ui-loading-empty-error"></a>
## 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 dune vue.
- **Contexte** : SPA ou webapp consommant des données asynchrones (API, backend, cache).
- **Quand lutiliser** : dès quune vue dépend de données externes ou dun 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 derreur compréhensible pour lutilisateur
- [ ] États testables individuellement
- [ ] Accessibilité respectée (focus, lecture écran)
- [ ] Pas de logique métier cachée dans le rendu
---
<a id="pattern-separation-server-state-client-state"></a>
## 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 lutiliser** : dès que lapplication 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 lapp 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
---
<a id="pattern-formulaire-robuste"></a>
## 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 lutiliser** : dès quun formulaire dépasse un simple champ isolé.
- **Quand léviter** : formulaires ultra-simples sans validation réelle.
### Analyse
- **Avantages** :
- UX claire (lutilisateur sait quoi corriger)
- Moins derreurs 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 derreur 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
---
<a id="pattern-navigation-reactive-post-action-async"></a>
## 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)
- [ ] Convention documentée dans la story foundations / project-context avant les premiers écrans
---
### 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 darchitecture 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 nentre pas encore ici