In Vuex, what is the logic of having both \"actions\" and \"mutations?\"
I understand the logic of components not being able to modify state (which seems smart), but
This confused me too so I made a simple demo.
component.vue
<template>
<div id="app">
<h6>Logging with Action vs Mutation</h6>
<p>{{count}}</p>
<p>
<button @click="mutateCountWithAsyncDelay()">Mutate Count directly with delay</button>
</p>
<p>
<button @click="updateCountViaAsyncAction()">Update Count via action, but with delay</button>
</p>
<p>Note that when the mutation handles the asynchronous action, the "log" in console is broken.</p>
<p>When mutations are separated to only update data while the action handles the asynchronous business
logic, the log works the log works</p>
</div>
</template>
<script>
export default {
name: 'app',
methods: {
//WRONG
mutateCountWithAsyncDelay(){
this.$store.commit('mutateCountWithAsyncDelay');
},
//RIGHT
updateCountViaAsyncAction(){
this.$store.dispatch('updateCountAsync')
}
},
computed: {
count: function(){
return this.$store.state.count;
},
}
}
</script>
store.js
import 'es6-promise/auto'
import Vuex from 'vuex'
import Vue from 'vue';
Vue.use(Vuex);
const myStore = new Vuex.Store({
state: {
count: 0,
},
mutations: {
//The WRONG way
mutateCountWithAsyncDelay (state) {
var log1;
var log2;
//Capture Before Value
log1 = state.count;
//Simulate delay from a fetch or something
setTimeout(() => {
state.count++
}, 1000);
//Capture After Value
log2 = state.count;
//Async in mutation screws up the log
console.log(`Starting Count: ${log1}`); //NRHG
console.log(`Ending Count: ${log2}`); //NRHG
},
//The RIGHT way
mutateCount (state) {
var log1;
var log2;
//Capture Before Value
log1 = state.count;
//Mutation does nothing but update data
state.count++;
//Capture After Value
log2 = state.count;
//Changes logged correctly
console.log(`Starting Count: ${log1}`); //NRHG
console.log(`Ending Count: ${log2}`); //NRHG
}
},
actions: {
//This action performs its async work then commits the RIGHT mutation
updateCountAsync(context){
setTimeout(() => {
context.commit('mutateCount');
}, 1000);
}
},
});
export default myStore;
After researching this, the conclusion I came to is that mutations are a convention focused only on changing data to better separate concerns and improve logging before and after the updated data. Whereas actions are a layer of abstraction that handles the higher level logic and then calls the mutations appropriately