12 juillet 2026 · Nuxt · Composables · Vue

Les composables en Nuxt : c'est quoi, quand et dans quels cas

Un composable n'est pas juste une fonction rangée dans un dossier : c'est le bon endroit pour la logique réactive réutilisable. Quand en écrire un, et quand s'en abstenir.

« Composable » est l'un de ces mots qui semblent évidents jusqu'au moment où il faut décider si un bout de code en mérite un. On finit par en créer trop peu (et copier-coller de la logique), ou trop (et transformer chaque fonction en composable inutilement). Voici ma façon de trancher.

Ce qu'est vraiment un composable

Un composable est une fonction, par convention préfixée par use, qui encapsule de la logique réactive en s'appuyant sur le système de réactivité de Vue (ref, computed, watch) et parfois sur le cycle de vie des composants (onMounted, onBeforeUnmount).

La distinction clé est là : une fonction utilitaire classique transforme des entrées en sorties et n'a pas de mémoire (formatDate(date)). Un composable, lui, détient un état qui vit dans le temps et réagit aux changements.

// app/composables/useCompteur.ts
export function useCompteur(pasInitial = 1) {
  const valeur = ref(0)
  const pas = ref(pasInitial)

  const doubler = computed(() => valeur.value * 2)
  const incrementer = () => { valeur.value += pas.value }
  const reinitialiser = () => { valeur.value = 0 }

  return { valeur, doubler, incrementer, reinitialiser }
}

Rangé dans app/composables/, il est auto-importé partout, sans ligne d'import :

<script setup lang="ts">
const { valeur, doubler, incrementer } = useCompteur(5)
</script>

Les composables que Nuxt vous donne déjà

Avant d'écrire le vôtre, sachez que Nuxt en fournit une famille très utilisée. Les connaître évite de réinventer :

  • useState : un état réactif partagé et compatible SSR (voir l'article dédié à la gestion d'état).
  • useFetch et useAsyncData : récupérer des données avec cache, déduplication et gestion des états de chargement.
  • useRoute et useRouter : lire la route courante et naviguer.
  • useRuntimeConfig : accéder à la configuration exposée à l'exécution.
  • useCookie : lire et écrire un cookie de façon réactive.

Beaucoup de besoins sont déjà couverts. Le composable maison arrive quand aucun de ceux-là ne répond exactement à votre cas.

Quand écrire un composable

Trois signaux clairs :

1. La même logique réactive apparaît dans plusieurs composants. Deux pages qui gèrent un formulaire avec les mêmes règles de validation, deux écrans qui écoutent la même source de données : extrayez la logique dans un composable et les deux la partagent sans duplication.

2. Un composant devient gros à cause de sa logique, pas de son template. Si votre <script setup> dépasse largement votre <template>, c'est souvent que plusieurs préoccupations cohabitent. Les découper en composables (useFiltres, usePagination, useSelection) rend chacune testable et nommée.

3. Vous manipulez une API du navigateur avec du cycle de vie. Un écouteur d'événement, un IntersectionObserver, un matchMedia : tout ce qui doit s'installer au montage et se nettoyer à la destruction est un candidat naturel. Le composable useReveal de ce site, par exemple, encapsule un IntersectionObserver et son nettoyage : le composant appelant ignore tout de cette mécanique, il appelle useReveal() et c'est réglé.

Quand ne PAS en écrire un

Le réflexe inverse est tout aussi important.

  • Une transformation pure, sans état : c'est un utilitaire, pas un composable. formatPrix(montant) va dans utils/, pas dans composables/. Le préfixe use sur une fonction sans réactivité est un faux signal qui trompe le lecteur.
  • Un besoin de structure visuelle réutilisable : c'est un composant, pas un composable. Si vous voulez réutiliser du markup, écrivez un .vue.
  • De la logique utilisée à un seul endroit et qui ne grossit pas : laissez-la dans le composant. Extraire par principe, alors qu'il n'y a ni duplication ni complexité, ajoute un fichier et un niveau d'indirection pour rien.

Les deux règles à ne pas violer

Un composable doit s'appeler au niveau supérieur du setup, jamais dans une condition ou une boucle, exactement comme les hooks. C'est ce qui permet à Vue d'associer correctement l'état réactif au composant.

Et il doit retourner ses ref sans les déballer. Retournez valeur (le ref), pas valeur.value : sinon le composant appelant reçoit une valeur figée, déconnectée de la réactivité. C'est l'erreur de débutant la plus fréquente sur les composables.

La leçon

La bonne question n'est pas « est-ce que je peux en faire un composable » (on peut presque toujours), mais « est-ce que ce code détient de l'état réactif, et est-ce que je le réutilise ou le sépare pour de bonnes raisons ». État réactif plus réutilisation ou clarté : composable. Simple transformation : utilitaire. Structure visuelle : composant. Avec ces trois cases, on range juste, et le projet reste lisible.

← Tous les articles