Progression
0 %
0/32 étapes terminées
Avancé · 12 min de lecture
Architecture et gestion d'état
Ranger une app qui grandit sans qu'elle s'effondre
1Définition
L'architecture d'une app React Native consiste à séparer clairement l'état serveur (données distantes, cache, synchronisation), l'état client (préférences, interface) et le code par fonctionnalité, pour que chaque changement reste local.
2Principes fondamentaux
01
L'état serveur n'est pas de l'état local
Les données distantes ont un cycle de vie propre : cache, invalidation, rechargement, erreurs. TanStack Query les gère mieux qu'un useEffect par écran.
02
Un état client minimal
Pour l'état partagé côté client (session, thème, panier), un store léger comme Zustand ou un Context bien découpé suffit.
03
Découper par fonctionnalité
Regroupe écrans, composants, hooks et requêtes d'une même fonctionnalité (features/panier/…) plutôt que par type de fichier.
04
Des frontières explicites
Les écrans orchestrent, les composants affichent, les hooks encapsulent la logique, les services parlent à l'API.
3Exemples pratiques
Données serveur avec TanStack Query
1import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';2 3export function useCours() {4 return useQuery({5 queryKey: ['cours'],6 queryFn: () => api.get('/cours'),7 staleTime: 60_000,8 });9}10 11export function useTerminerLecon() {12 const client = useQueryClient();13 return useMutation({14 mutationFn: (id) => api.post('/lecons/' + id + '/terminer'),15 onSuccess: () => client.invalidateQueries({ queryKey: ['cours'] }),16 });17}Cache, états de chargement, rechargement au retour sur l'écran et invalidation après mutation, sans un seul useEffect.
État client avec Zustand
1import { create } from 'zustand';2 3export const useSession = create((set) => ({4 utilisateur: null,5 connecter: (utilisateur) => set({ utilisateur }),6 deconnecter: () => set({ utilisateur: null }),7}));8 9// Dans un composant : ne s'abonne qu'à ce qu'il lit10const utilisateur = useSession((s) => s.utilisateur);Le sélecteur limite les rendus aux composants concernés.
4Erreurs courantes
Tout mettre dans un Context géant
À éviter
<AppContext.Provider value={{ utilisateur, panier, theme, notifications, … }}>À faire
// un store par domaine, lu avec des sélecteursPourquoi : Chaque changement de n'importe quelle valeur re-rend tous les consommateurs du Context.
Copier les données serveur dans un store global
À éviter
useEffect(() => { api.get('/cours').then(setCoursDansLeStore); }, []);À faire
const { data: cours } = useCours();Pourquoi : Tu réinventes le cache, la déduplication et l'invalidation, avec des bugs de synchronisation.
5Subtilités à connaître
- ◆Les mises à jour optimistes (
onMutate) donnent une interface instantanée, avec retour arrière en cas d'erreur. - ◆
persistQueryClientet un stockage local rendent l'app utilisable hors ligne avec les dernières données connues. - ◆Rafraîchir les requêtes quand l'app revient au premier plan passe par
focusManageretAppState.
6Techniques d'expert
Précharger l'écran suivant
queryClient.prefetchQuery au survol ou à l'apparition d'une carte : quand l'utilisateur ouvre le détail, les données sont déjà là.
Des clés de requêtes structurées
Organise tes queryKey comme une arborescence (['cours', id, 'lecons']) pour invalider précisément une branche.
Tester la logique hors de l'interface
Les stores Zustand et les hooks de requêtes se testent sans rendu d'écran : la logique métier reste vérifiable.
7Sur le terrain
- Les applis de livraison mettent à jour le panier de façon optimiste pour paraître instantanées.
- Les applis de banque séparent strictement session (sécurisée) et données de compte (rechargées souvent).
- Les équipes nombreuses découpent par fonctionnalité pour limiter les conflits de fusion.
8Vérifie ta compréhension
Question 1/3
Score 0
Quel outil pour les données distantes avec cache ?
Envie d'essayer ? Ouvre le Labo et recopie les exemples pour les modifier.