• 15 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 08/03/2022

Modifiez vos données dans Vuex

Découvrez les mutations

Dans le chapitre précédent, nous avons appris à définir notre espace de stockage de données dans Vuex avec  state  et des accesseurs, mais également à récupérer nos données avec des méthodes comme  mapState  et  mapGetters. Dans ce chapitre, nous allons passer à l'étape suivante dans la gestion de notre data store : mettre à jour et modifier nos données dans Vuex avec les mutations.

Comme nous l'avons vu dans la structure initiale de store.js :

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {

    },
    mutations: {

    },
    actions: {
    
    }
})

 La deuxième clé définie dans le store est appelée mutation. Comme son nom l'indique, elle contiendra un objet de toutes les propriétés responsables de modifications du  state.

Définissez une mutation

Si nous prenons l'exemple traditionnel du compteur, nous pouvons définir une mutation comme suit :

export default new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        INCREASE_COUNT(state) {
            state.count += 1
        }
    },
    actions: {

    }
})

Par défaut, la mutation reçoit le  state  en premier argument. Ce dernier peut ensuite être utilisé pour effectuer les modifications nécessaires. Dans l'exemple ci-dessus, nous ne faisons qu'incrémenter  state.count  de 1.

Cependant,  cette technique a ses limites car nous pourrions envisager de rendre la valeur incrémentée dynamique. Heureusement, les mutations peuvent prendre un deuxième argument : le paramètre payload.

export default new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        INCREASE_COUNT(state, payload) {
            state.count += Number(payload)
        }
    },
    actions: {

    }
})

Dans l'exemple révisé, nous autorisons maintenant l'utilisateur à :

  • transmettre de combien nous voulons que  state.count  soit incrémentée ;

  • fixer une valeur par défaut de 1, au cas où l'utilisateur oublie de transmettre une valeur :

  • convertir la valeur en nombre pour qu'elle ne s'ajoute pas comme chaîne de caractères par accident.

Actez une mutation

Lorsqu'il s'agit de modifier le state d'une application, il est essentiel que cela soit fait au bon moment. En d'autres termes, une attention et un soin particuliers sont accordés à ces événements, afin de s'assurer que toute erreur soit facilement identifiée. Par conséquent, plutôt que d'invoquer la mutation comme une fonction normale, nous utilisons une action spéciale : commit.

Lorsqu'une mutation est actée, l'action commit prend deux paramètres :

  • nom de la mutation ;

  • payload (facultatif).

this.$store.commit('INCREMENT_COUNT', 2)

Lorsqu'une mutation est actée, la modification est faite immédiatement. En d'autres termes, les mutations Vuex sont synchrones, ce qui signifie qu'il n'est par exemple pas possible de récupérer des données d'une API dans une mutation.

Bien sûr, vous vous demandez probablement de quelle manière il faudrait acter les mutations. Pour répondre à cette question, nous allons devoir parler des actions.

Découvrez les actions

Jusqu'à présent, nous avons appris que :

  •  State  contient notre data store global ;

  • les accesseurs (getters) servent de propriétés calculées à nos espaces de stockage de données ;

  • les mutations nous permettent de mettre à jour/modifier le state.

La dernière pièce du puzzle est les actions. Elles nous servent à coordonner la logique derrière les mutations. En d'autres termes, elles sont similaires à la propriété  methods  dans une instance de Vue.

Les actions dans le store Vuex sont similaires à la propriété methods dans une instance Vue
Les actions dans le store Vuex sont similaires à la propriété methods dans une instance Vue

Définissez une action

Pour continuer avec notre exemple de compteur, nous pourrions définir notre action de la façon suivante :

export default new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        INCREASE_COUNT(state, amount = 1) {
            state.count += Number(amount)
        }
    },
    actions: {
        incrementCount(context, amount) {
            context.commit('INCREMENT_COUNT', amount)
        }
    }
})

 Une action est composée d'un nom, du paramètre  context  et d'un payload optionnel (comme pour les mutations). Dans l'exemple ci-dessus :

  • incrementCount  est le nom de l'action ;

  • le paramètre  context  nous donne accès aux mêmes méthodes et propriétés dans l'instance du store Vuex (par exemple, commit, state, getters, etc.) ;

  • amount est le payload que nous devons transmettre à la mutation, afin qu'elle augmente de la bonne valeur.

Découvrez l'utilité des actions

Sur la base de l'exemple ci-dessus, vous vous demandez peut-être pourquoi ne pas simplement appeler la mutation directement. Mais que se passerait-il lorsqu'il faut diminuer le  count  d'une certaine valeur ?

export default new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        INCREASE_COUNT(state, amount = 1) {
            state.count += Number(amount)
        },
        DECREASE_COUNT(state, amount = 1) {
            state.count -= Number(amount)
        }
    },
    actions: {
        incrementCount(context, amount) {
            context.commit('INCREMENT_COUNT', amount)
        }
    }
})

Une certaine logique est nécessaire pour déterminer quand déclencher chaque mutation. Pour tenir compte de cela, rendons notre action générique de la manière suivante :

export default new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        INCREASE_COUNT(state, amount = 1) {
            state.count += Number(amount)
        },
        DECREASE_COUNT(state, amount = 1) {
            state.count -= Number(amount)
        }
    },
    actions: {
        updateCount(context, amount) {
            if (amount >= 0) {
                context.commit('INCREASE_COUNT', amount)
            } else {
                context.commit('DECREASE_COUNT', amount)
            }
        }
    }
})

Pourquoi ne pas simplement réunir les mutations en une seule ?

Nous pourrions rendre la mutation générique à quelque chose comme  CHANGE_COUNT, mais en regardant l'historique, cela nous fournirait moins de détails, ce qui rend les choses plus difficiles à débugger. Par conséquent, il est préférable que les mutations gardent un seul usage. Laissez la logique aux actions.

De plus, comme le paramètre  context  peut être utilisé pour accéder à de nombreuses propriétés différentes du store Vuex, vous allez découvrir une technique de codage courante qui est l'affectation par décomposition (desctructuring, en anglais). Elle est faite pour simplifier le code et le rendre plus facile à lire. Avec notre exemple, cela ressemblerait à ce qui suit :

export default new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        INCREASE_COUNT(state, amount = 1) {
            state.count += Number(amount)
        },
        DECREASE_COUNT(state, amount = 1) {
            state.count -= Number(amount)
        }
    },
    actions: {
        updateCount({ commit }, amount) {
            if (amount >= 0) {
                commit('INCREASE_COUNT', amount)
            } else {
                commit('DECREASE_COUNT', amount)
            }
        }
    }
})

En plus de nous donner la liberté de déterminer la logique du moment où les mutations sont déclenchées, les  actions  sont asynchrones. Cela signifie que vous ne pouvez appeler des API et acter des mutations qu'en cas de réussite. Ou en fonction de ce que vous souhaitez réaliser.

Maintenant que nous savons comment définir les actions, la question suivante se pose : comment les utiliser dans nos composants ?

Utilisez les actions dans les composants

Tout comme il existe un terme spécial pour invoquer les mutations (c'est-à-dire acter ou « commit »), il existe aussi un terme spécial pour les actions : propager (dispatch). En d'autres termes, vous envoyez l'action pour exécuter une tâche. Donc, si vous vouliez propager une action depuis votre composant, cela ressemblerait à ce qui suit :

<template>
    <div>
        <p>{{ count }}</p>
        <button @click="sendUpdateCountAction">Increment</button>
    </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
    computed: {
        ...mapState(['count'])
    },
    methods: {
        sendUpdateCountAction() {
            this.$store.dispatch('updateCount')
        }
    }
}
</script>

Cependant, comme pour  mapState  et  mapGetters, il existe un équivalent pour les actions :  mapActions

<template>
    <div>
        <p>{{ count }}</p>
        <button @click="updateCount">Increment</button>
    </div>
</template>
 
<script>
import { mapState, mapActions } from 'vuex'
 
export default {
    computed: {
        ...mapState(['count'])
    },
    methods: {
        ...mapActions(['updateCount'])
    }
}
</script>

Vous connaissez maintenant les principaux éléments de Vuex !

Entraînez-vous

Vous trouverez le code source des exercices dans le repo GitHub du cours, dans le dossier  cafe-with-a-view. Pour commencer, consultez la branche  P4C4-Begin.

Instructions

  1. Migrez l'événement d'ajout au panier de  Home.vue  et  MenuItem.vue  vers Vuex.

  2. Créez une mutation qui met à jour le  state  du shoppingCart.

  3. Créez une action qui peut être déclenchée depuis  MenuItem.vue  qui met à jour le panier d'achat dans  Home.vue

En résumé

Dans ce chapitre, vous avez découvert :

  •     ce que sont les mutations et les actions ;

  •     comment utiliser les mutations pour mettre à jour le state ;

  •     comment utiliser les actions pour gérer vos mutations ;

  •     comment déclarer et utiliser des actions dans vos composants.

C'est maintenant le moment de passer en revue nos acquis de la partie. Rendez-vous au prochain chapitre !

Exemple de certificat de réussite
Exemple de certificat de réussite