aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Développement Web

Vue Pinia pour la gestion d'état : oublier Vuex

vue pinia est la façon officielle, et aujourd'hui recommandée, de gérer l'état partagé dans les applications Vue 3. Lorsque plusieurs composants ont besoin des mêmes données — l'utilisateur connecté, le panier, la préférence de thème — tu veux les garder à un seul endroit central. L'ancien standard pour cela était Vuex, mais l'équipe Vue recommande désormais Pinia pour les nouveaux projets. Dans cet article, nous allons voir pas à pas comment construire un store de zéro avec Pinia plutôt qu'avec Vuex.

Pourquoi Pinia plutôt que Vuex ?

Pinia est la bibliothèque officielle de gestion d'état qui remplace Vuex, et elle est préférée parce qu'elle résout plusieurs problèmes concrets :

  • Moins de cérémonie : dans Vuex, il fallait écrire des mutations pour modifier quoi que ce soit. Pinia supprime totalement la notion de mutation ; tu modifies l'état directement ou depuis les actions.
  • Support TypeScript complet : les types sont déduits automatiquement ; this et les valeurs de retour sont typés sans code répétitif.
  • Pas de modules, des stores plats : au lieu de la structure imbriquée de Vuex, chaque store est une unité indépendante. Tu appelles n'importe quel store depuis n'importe où.
  • Conçu pour la Composition API : Pinia fonctionne naturellement avec la logique setup de Vue 3 et offre le support des devtools.

En bref, Pinia fait tout ce que faisait Vuex avec moins de code et une meilleure sécurité de typage. Si tu as déjà un projet Vuex, tu n'es pas obligé de migrer de force, mais écrire les nouveaux stores avec Pinia est judicieux.

Installer et enregistrer Pinia

Installe d'abord le paquet, puis crée une instance avec createPinia() et enregistre-la sur ton application :

npm install pinia
// main.js
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";

const app = createApp(App);
app.use(createPinia());
app.mount("#app");

C'est tout. Tu peux maintenant définir et utiliser des stores partout dans l'application. À la place de l'unique objet store géant de Vuex, avec Pinia tu crées plusieurs petits stores.

Ton premier store : state, getters et actions

Un store se définit avec defineStore. Le premier argument est un identifiant unique (utilisé par les devtools), le second est le contenu du store. Voici l'exemple classique du compteur :

// stores/counter.js
import { defineStore } from "pinia";

export const useCounterStore = defineStore("counter", {
  state: () => ({
    count: 0,
    name: "Compteur",
  }),
  getters: {
    double: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++;
    },
    reset() {
      this.count = 0;
    },
  },
});

On distingue les trois éléments centraux :

  • state : une fonction qui renvoie les données initiales. Le fait que ce soit une fonction garantit que chaque instance reçoit son propre état neuf.
  • getters : des valeurs calculées dérivées de l'état. Elles sont mises en cache comme le computed de Vue ; ici double n'est pas recalculé tant que count ne change pas.
  • actions : des méthodes qui modifient l'état et contiennent ta logique métier. Contrairement à Vuex, il n'y a pas de séparation synchrone/asynchrone ; une action peut être async directement.

Remarque qu'il n'y a aucune section mutations comme dans Vuex. Quand tu veux modifier l'état, tu écris simplement this.count++ dans une action.

Utiliser le store dans un composant

Pour utiliser un store, tu l'appelles dans setup. L'objet retourné est réactif, donc tu peux l'utiliser directement dans le template :

<script setup>
import { useCounterStore } from "@/stores/counter";

const counter = useCounterStore();
</script>

<template>
  <p>Compteur : {{ counter.count }}</p>
  <p>Double : {{ counter.double }}</p>
  <button @click="counter.increment()">Incrémenter</button>
  <button @click="counter.reset()">Réinitialiser</button>
</template>

Ici counter.count, counter.double et counter.increment() sont directement accessibles. Tu lis l'état dans le template et tu déclenches une action d'un clic.

storeToRefs : déstructurer sans perdre la réactivité

Souvent tu veux extraire quelques champs du store et les utiliser avec des noms courts. Mais si tu déstructures le store directement, la réactivité est perdue :

// FAUX — count n'est plus réactif
const { count, double } = useCounterStore();

La bonne méthode est d'utiliser storeToRefs pour le state et les getters. Cet utilitaire renvoie chaque champ sous forme de ref réactive. Les actions, étant des fonctions, peuvent être déstructurées directement :

import { storeToRefs } from "pinia";

const store = useCounterStore();
const { count, double } = storeToRefs(store); // reste réactif
const { increment, reset } = store;           // actions prises telles quelles

Actions asynchrones et mises à jour groupées

Dans les vraies applications, les actions font souvent des appels API. Contrairement à Vuex, tu n'as pas besoin d'une construction séparée ; il suffit de rendre l'action async :

actions: {
  async fetchUser(id) {
    this.loading = true;
    try {
      const res = await fetch(`/api/users/${id}`);
      this.user = await res.json();
    } finally {
      this.loading = false;
    }
  },
}

Si tu veux mettre à jour plusieurs champs d'un coup, tu peux utiliser $patch ; c'est suivi comme un seul changement et c'est plus propre dans les devtools :

store.$patch({ count: 10, name: "Nouveau" });

Tu peux aussi réinitialiser l'état à sa valeur initiale avec store.$reset(), et écouter chaque changement avec store.$subscribe() (par exemple pour écrire dans le localStorage). Ce sont de petits détails précieux qui montrent à quel point Pinia simplifie le travail quotidien par rapport à Vuex.

Questions fréquentes

Dois-je utiliser Pinia ou Vuex ?

Pinia pour les nouveaux projets Vue 3. La recommandation officielle de Vue est désormais Pinia, et Vuex est en mode maintenance. Si tu as un gros projet Vuex existant, une migration urgente n'est pas nécessaire, mais écrire les nouvelles fonctionnalités avec Pinia est le choix le plus pérenne.

Pourquoi n'y a-t-il pas de mutations dans Pinia ?

Vuex imposait les mutations pour que les devtools puissent suivre les changements. Comme Pinia peut suivre directement les changements d'état, cette couche intermédiaire est devenue inutile ; tu modifies l'état dans une action ou avec $patch, et les devtools enregistrent quand même chaque étape.

Plusieurs stores peuvent-ils communiquer entre eux ?

Oui. Dans l'action ou le getter d'un store, tu peux appeler un autre store : tu invoques la fonction useOtherStore() correspondante et tu utilises l'instance retournée. Les stores peuvent s'atteindre sans la complexité des namespaces de modules de Vuex.

Une architecture d'état bien structurée est la colonne vertébrale d'une application Vue qui grandit. Si tu construis un projet Vue 3 + Pinia ou que tu veux moderniser du code Vuex existant, contacte-moi — mettons en place ensemble une structure propre et évolutive.

Bu kategorideki tüm yazılar →

Devamı için