# Frontend — Patterns : State > Extrait de la base de connaissance Lead_tech. Voir `knowledge/frontend/patterns/README.md` pour l'index complet. --- ## 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 : Refresh idempotent sur store de liste paginée ### Synthèse - **Objectif** : garantir qu'un pull-to-refresh recharge une liste paginée sans doublons, sans courses réseau et sans état intermédiaire incohérent. - **Contexte** : app mobile ou SPA avec store de domaine (ex. Zustand) et pagination incrémentale. - **Quand l'utiliser** : dès qu'une même liste supporte à la fois `loadMore` et `refresh`. - **Quand l'éviter** : listes purement statiques ou données entièrement remplacées sans pagination. ### Analyse - **Avantages** : - évite les doublons lors des refresh concurrents - garde une transition atomique entre ancien et nouvel état - rend le comportement async testable côté store - **Limites / vigilance** : - impose une discipline claire entre `refresh` et `loadMore` - demande une clé d'identité stable pour dédupliquer les items ### Validation - Validé le : 10-03-2026 - Contexte technique : React Native / Expo / Zustand / listes paginées ### Implémentation (exemple minimal) ```txt - conserver une promesse de refresh partagée tant qu'un refresh est en vol - refuser ou réutiliser tout refresh concurrent au lieu d'en lancer un second - remplacer atomiquement la liste à la fin du refresh - dédupliquer les items par identifiant au merge des pages suivantes - empêcher `loadMore` de fusionner sur un snapshot devenu obsolète ``` ### Checklist - [ ] Une seule promesse de refresh en vol à la fois - [ ] `refresh` et `loadMore` ont des garde-fous explicites - [ ] La liste est remplacée atomiquement après refresh - [ ] Les pages suivantes sont dédupliquées par identifiant stable - [ ] Tests sur refresh concurrent + refresh suivi de pagination --- ## Pattern : UI admin légère sur domaine existant ### Synthèse - **Objectif** : ajouter une capacité interne simple sans ouvrir trop tôt un back-office séparé ni dupliquer la logique métier. - **Contexte** : app mobile ou SPA avec un domaine métier déjà structuré et quelques actions internes ponctuelles. - **Quand l'utiliser** : publication, activation, modération légère, bascule de statut, action opérateur simple. - **Quand l'éviter** : permissions complexes, workflows multiples, audit riche ou volume d'actions qui justifie un vrai espace d'administration. ### Analyse - **Avantages** : - réutilise le service et le store métier existants - limite le coût de structure pour une capacité admin mince - garde les mutations testables et lisibles - **Limites / vigilance** : - ne pas laisser cette approche dériver vers un pseudo back-office implicite - le refresh après mutation doit être explicite sur les vues impactées ### Validation - Validé le : 10-03-2026 - Contexte technique : React Native / Expo Router / store de domaine ### Implémentation (exemple minimal) ```txt - ajouter une route dédiée minimale pour l'action interne - réutiliser le service/store métier existant au lieu de créer une couche parallèle - afficher le statut courant avant action - bloquer les actions concurrentes avec un flag explicite (`isUpdating*`) - déclencher un refresh explicite des vues impactées après succès - éviter les mutations en fire-and-forget ``` ### Checklist - [ ] Route dédiée minimale, pas de mini back-office générique - [ ] Réutilisation du domaine métier existant - [ ] Garde-fou explicite contre les doubles actions - [ ] Refresh explicite après mutation réussie - [ ] Tests sur succès, erreur et action concurrente