Mutations
Change state with mutations — the only way to modify store state, ensuring all changes are trackable and synchronous.
Mutations
You should never change state directly. Instead, you commit mutations — synchronous functions that are the only sanctioned way to modify state. This makes every state change trackable and debuggable.
Why Not Just Change State Directly?
// BAD — direct state manipulation
this.$store.state.products[0].price = 5;
// GOOD — commit a mutation
this.$store.commit('reducePrice', 4);
Direct changes are untraceable. Vue DevTools cannot detect them, you cannot track who changed what, and it makes debugging a nightmare. Mutations create a log of every state change.
Defining Mutations
// store/store.js
export const store = new Vuex.Store({
state: {
products: [
{ id: 1, name: 'Banana Skin', price: 20 },
{ id: 2, name: 'Shiny Star', price: 40 },
{ id: 3, name: 'Green Shells', price: 60 },
{ id: 4, name: 'Red Shells', price: 80 },
{ id: 5, name: 'Mushroom', price: 15 }
]
},
mutations: {
reducePrice(state, amount) {
state.products.forEach(product => {
product.price -= amount;
});
}
}
});
Each mutation receives state as the first argument and an optional payload as the second argument. The payload can be a number, string, or object.
Committing Mutations from Components
<template>
<div>
<button @click="reducePrice">Reduce Prices by $4</button>
</div>
</template>
<script>
export default {
methods: {
reducePrice() {
this.$store.commit('reducePrice', 4);
}
}
};
</script>
this.$store.commit('mutationName', payload) calls the mutation. The store updates, getters recompute, and all components that read from the affected state re-render.
Object-Style Commit
// Payload as an object
this.$store.commit({
type: 'reducePrice',
amount: 4
});
// In the mutation:
mutations: {
reducePrice(state, payload) {
state.products.forEach(p => {
p.price -= payload.amount;
});
}
}
Rules of Mutations
| Rule | Reason |
|---|---|
| Must be synchronous | DevTools tracks mutations — async breaks the timeline |
| Should be the only way to change state | Creates a traceable log of all state changes |
| Receive state and an optional payload | State is what you modify; payload is the data needed |
Key Takeaways
- Mutations are the only way to change Vuex state — commit them with
this.$store.commit() - They receive
stateand an optional payload (data to use in the change) - Mutations must be synchronous — for async operations, use actions (next episode)
- Every mutation is logged by Vue DevTools for time-travel debugging