← Journal technique

frontend

Zustand : rien du cérémonial de Redux, et le bazar que ça invite

Zustand : rien du cérémonial de Redux, et le bazar que ça invite

Une petite bibliothèque d'état qui saute presque tout le cérémonial de Redux — pas de providers, pas de boilerplate actions/reducers/dispatch, pas de problèmes de re-render de Context. Un store n'est qu'une fonction :

const useQueueStore = create<QueueState>((set) => ({
  tokens: [],
  addToken: (token) => set((state) => ({ tokens: [...state.tokens, token] })),
}));

const tokens = useQueueStore((state) => state.tokens);

Par rapport à React Context : Context re-render chaque consommateur dès qu'une partie de la valeur change, à moins de le découper en beaucoup de petits contextes soigneusement mémoïsés — ce que la plupart des gens ne font pas correctement, et ça devient ingérable au-delà de quelques bouts d'état partagé. Le pattern de sélecteur de Zustand re-render un composant seulement quand la tranche qu'il a sélectionnée change — de meilleures performances vraiment gratuites, sans la discipline de mémoïsation manuelle dont Context a besoin pour obtenir le même résultat.

Par rapport à Redux : la valeur de Redux, c'est un état strict, traçable, débogable en voyage-dans-le-temps pour de très grosses applications avec beaucoup de contributeurs, et le cérémonial ne se rentabilise qu'à cette échelle. Pour une poignée d'applications ciblées avec un état assez contenu — file courante, ticket courant, statut de connexion — ce cérémonial est surtout de la surcharge.

Pour une application temps réel multi-appareils en particulier, l'essentiel de l'état front-end, c'est « qu'est-ce que la connexion en direct dit être vrai en ce moment ». Les stores Zustand marchent bien comme cible d'atterrissage pour les handlers de socket — un événement entrant met à jour le store directement, et chaque composant qui le lit se re-render automatiquement :

socket.on("queueUpdated", (data) => {
  useQueueStore.getState().setQueue(data);
});

Le compromis : Zustand n'impose pas beaucoup de structure. Rien n'empêche une base de code de finir avec beaucoup de petits stores ad hoc aux frontières floues à moins d'une convention délibérée — un store par vrai concept de domaine, pas un par composant. L'absence de cérémonial qui le rend rapide à utiliser est la même chose qui n'arrêtera pas un bazar si personne ne fait attention aux frontières des stores à mesure que l'application grossit.