Vuex - Vue State Management - Part III - Mutations
Updating the global state using mutations

Search for a command to run...
Updating the global state using mutations

Thanks SOVANNARO! Part 4 will be coming soon!
In this series, I will discuss state management in Vue using Vuex and provide examples for a better understanding.
Component Communication & Introduction to State Management
Developers often tell me that the requirements they receive are usually vague and unclear. Another common complaint is that the requirements change midway, causing them to get stuck. Additionally, sometimes the deadline is set before the requirements...

Imagine you've got a REST API for listing users, and each user's information shows up in 12 fields. GET /v1/users/?page=1&page_size=15 { "pagination_data": { "total_records": 10000, "pages": 667, "prev_page_no": null, ...

Decoupling the Data Layer for Enhanced Code Modularity

Essentials for Safeguarding and Maintaining Your Sprint Cycles

A Step-by-Step Tutorial with Practical Examples

Once we have our state and getters ready as explained in part II of this blog, we can start defining our mutations.
Mutations are functions that are used to change/ modify your Vuex store. You cannot directly call your mutations instead a mutation can be invoked using store.commit.
In the previous part, we defined our state and the getters. Let's create a mutation handler called CLEAR_WALLET_BALANCE which sets the walletBalance in the state to 0.
// store/index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
userId: 101,
deliveryPincode: "400068",
walletBalance: 100.54,
products: [
{ id: 1, title: "Samsung S21", price: 100 },
{ id: 2, title: "Macbook Pro", price: 200 },
{ id: 3, title: "Macbook Air", price: 300 },
{ id: 4, title: "Apple iPad", price: 400 },
{ id: 5, title: "Apple Watch", price: 500 },
],
wishlist: [
{ id: 2, title: "Macbook Pro", isOutOfStock: false },
{ id: 4, title: "Apple iPad", isOutOfStock: true },
{ id: 5, title: "Apple Watch", isOutOfStock: true },
],
cart: [
{ id: 4, title: "Apple iPad", price: 400, quantity: 1 },
{ id: 5, title: "Apple Watch", price: 500, quantity: 2 },
],
},
getters: {
getCartTotalQuantity: (state) => {
const quantities = state.cart.map((item) => item.quantity);
return quantities.reduce((x, y) => x + y, 0);
},
getCartTotal: (state) => {
const itemPrices
= state.cart.map((item) => item.price * item.quantity);
return itemPrices.reduce((x, y) => x + y, 0);
},
getWishlistOutOfStockItems: (state) =>
state.wishlist.filter((item) => item.isOutOfStock).length,
},
mutations: {
CLEAR_WALLET_BALANCE (state) {
state.walletBalance = 0;
}
},
actions: {},
});
We can call or commit this mutation inside our component using this.$store.commit. Now, whenever the button is clicked, the clearWalletBalance() method is called and this method will commit the CLEAR_WALLET_BALANCE mutation.
// ClearWalletBalance.vue
<template>
<div>
<button @click="clearWalletBalance">Clear Wallet Balance</button>
</div>
</template>
<script>
export default {
methods: {
clearWalletBalance() {
this.$store.commit('CLEAR_WALLET_BALANCE');
}
},
};
</script>
We can also pass a value to our mutation and this value can be set to any value in the state. For example, we can create a mutation to update the Pincode.
SET_DELIVERY_PINCODE (state, newPinCode) {
state.deliveryPincode = newPinCode;
}
In the Component, the commit method will take the first parameter as the mutation name and the next parameter as the value.
// UpdatePinCode.vue
<template>
<div>
<input v-model="pinCode" type="text" />
<button @click="updatePinCode">Update Pincode</button>
</div>
</template>
<script>
export default {
data() {
return {
pinCode: ""
}
},
methods: {
updatePinCode() {
this.$store.commit('SET_DELIVERY_PINCODE', this.pinCode);
}
},
};
</script>
Similarly, we can also pass an Object to the mutation.
DECREMENT_WALLET_BALANCE (state, payload) {
state.walletBalance = state.walletBalance - payload.amount;
}
this.$store.commit('DECREMENT_WALLET_BALANCE', {
amount: this.amount
});
The mapMutations helper method can be used inside our component to list which mutations are required by the component.
<script>
import { mapMutations } from "vuex";
export default {
methods: {
...mapMutations([
'CLEAR_WALLET_BALANCE',
// maps `this.CLEAR_WALLET_BALANCE()`
// to `this.$store.commit('CLEAR_WALLET_BALANCE')`
'SET_DELIVERY_PINCODE',
// maps `this.SET_DELIVERY_PINCODE(newPinCode)`
// to `this.$store.commit('SET_DELIVERY_PINCODE', newPinCode)`
'DECREMENT_WALLET_BALANCE'
// maps `this.DECREMENT_WALLET_BALANCE(payload)`
// to `this.$store.commit('DECREMENT_WALLET_BALANCE', payload)`
])
},
};
</script>
Instead of a list as an argument to mapMutations, we can pass an Object with key as a method name and value as the mutation name. Now, the method name will be mapped to the mutation name.
<script>
import { mapMutations } from "vuex";
export default {
methods: {
...mapMutations([
clearWalletBalance: 'CLEAR_WALLET_BALANCE',
// maps `this.clearWalletBalance()`
// to `this.$store.commit('CLEAR_WALLET_BALANCE')`
setDeliveryPincode: 'SET_DELIVERY_PINCODE',
// maps `this.setDeliveryPincode(newPinCode)`
// to `this.$store.commit('SET_DELIVERY_PINCODE', newPinCode)`
decrementWalletBalance: 'DECREMENT_WALLET_BALANCE'
// maps `this.decrementWalletBalance(payload)`
// to `this.$store.commit('DECREMENT_WALLET_BALANCE', payload)`
])
},
};
</script>
We can also create two-way binding with our Vuex state using mutations. Here, we create a computed property where the getter will take the fetch the value from the state and the setter will call the mutation when any update occurs.
// UpdatePinCode.vue
<template>
<div>
<input v-model="pinCode" type="text" />
</div>
</template>
<script>
export default {
computed: {
pinCode: {
get () {
return this.$store.state.deliveryPincode;
},
set (value) {
this.$store.commit('SET_DELIVERY_PINCODE', value)
}
}
}
};
</script>
This was all about mutations in Vuex. Next, we'll move to actions in Vuex!
Thanks for reading!