learn.chetana.fr

Composables : la logique réutilisable

11 min readCore

L'idée : une fonction qui retourne de l'état réactif

Un composable est une fonction useQuelqueChose() qui encapsule de la logique réactive et retourne des refs/fonctions :

// composables/useProgress.ts (celui de CETTE plateforme)
export function useProgress(courseSlug: string) {
  const progress = useState<ProgressMap>(`progress:${courseSlug}`, () => ({}))
  onMounted(async () => { /* fetch API ou localStorage, merge au login */ })
  async function setStatus(path: string, status: Status) { /* optimistic + PUT */ }
  return { progress, setStatus }
}

// N'IMPORTE quel composant :
const { progress, setStatus } = useProgress('ml-engineer')

Trois propriétés qui font la puissance du pattern :

  1. la composition : un composable peut en utiliser d'autres (useProgress utilise useState et useLogtoUser) — la logique s'assemble comme des fonctions, sans hiérarchie de classes ;
  2. l'état par appel : chaque composant qui appelle useX() obtient SON instance d'état (sauf état partagé volontaire type useState) — pas de singleton accidentel ;
  3. la testabilité : c'est une fonction — elle se teste sans monter de composant (nos tests de diffLocalVsRemote en sont l'exemple extrême : la logique pure extraite du composable).

Le cas d'école : les ~25 composables du front copilot

Le front du projet étudié découpe toute sa complexité en composables spécialisés : useCopilotSse (le parsing du stream), useCopilotMessages (l'historique affiché), useCopilotRun (le cycle de vie d'un run), useCopilotHitl (les approbations), useCopilotFrontendTools (les tools exécutés au navigateur)… Chacun une responsabilité, composés ensemble par la page. C'est la réponse front au « un fichier = une chose » du manifeste — et la raison pour laquelle un front de copilot temps réel reste maintenable.

Les règles d'hygiène

  • préfixe use, appelé au setup uniquement (pas dans un handler ou un if — les hooks de cycle de vie doivent s'enregistrer au bon moment) ;
  • retourne des refs, pas des valeurs (return { count } et non count.value — sinon la réactivité est perdue à la frontière) ;
  • l'I/O aux extrémités : le composable orchestre, les appels API vivent dans des fonctions dédiées — même règle que les services backend.
🧩 Quiz1/3

Un composable retourne des refs (et pas leurs .value) parce que…

🃏 Flashcards1/4