Vue.js State Managment with Vuex

Introduction

One of the essential aspects of Vue.js development is state management. There are not many state managers exists in Vue World. Vuex is an officially supported state manager for Vue.js applications and, you have to understand deeply Vuex before creating a vue.js application. Good state management makes the application more dynamic and more durable. Bad state management makes applications slow down, creates hard to debug software, decreases code quality.

  • State: What we store which types we will use.
  • Getters: How we get from the store,
  • Mutations: How we change the store.
  • Actions: How we change the store.
  • Modules: How we can split different stores.
const store = new Vuex.Store({
state: {

},
getters: {

},
mutations: {

},
actions: {

},
})

State

The state is the place where we store and define what our application needs. Before starting to explain the state, I would like to explain these two concepts:

  • Single source of truth
const store = new Vuex.Store({
state: {
people: []
},
getters: {

},
mutations: {

},
actions: {

},
})
const store = new Vuex.Store({
state: {
people: [
{ name: 'Kate', age: 30 },
{ name: 'Jack', age: 34 }, { name: 'John', age: 53 },
]
},
getters: {
},
mutations:
},
actions: {
},
})

Getters

After creating the state, we have to implement methods to get the information from the state. Getter methods are defined in the getter section of the store object. We can create method style or property style access methods. The first parameter of the getter is always state object.

getters: {
people(state){ // Shorthand property access.
return state.people;
},
firstPerson(state){ // Shorthand method access
return () => state.people[0];
},
lastPerson : function(state){ // Not shorthand, method access
return () => state.people[state.people.length - 1];
},
personByName(state){ // Shorthand method access with a field.
return (name) => state.people.filter(p=>p.name==name);
}
},
this.$store.getters.people; // Property access without brackets
this.$store.getters.firstPerson(); // Function access
this.$store.getters.lastPerson(); // Function access
this.$store.getters.personByName(name); // Function ac. with params
export default {
name: 'People',
components: {
},
methods: {
getPeople(){
return this.$store.getters.people;
},
getFirstPerson(){
return this.$store.getters.firstPerson();
},
getLastPerson(){
return this.$store.getters.lastPerson();
},
getPersonByName(name){
return this.$store.getters.personByName(name);
},
}
}
People: {{ getPeople() }} <br>
First: {{ getFirstPerson() }} <br>
Last: {{ getLastPerson() }} <br>
ByName: {{ getPersonByName("Jack") }} <br>

The mapGetters

You can create component methods by using mapGetters helper. The helper easily creates every method for the component without any additional definition. You can pass an array or an object to the `mapGetters` function. The difference is you can specify a different name when you pass an object.

export default {
name: 'People',
components: {
},
computed: {
...mapGetters([
'people',
'firstPerson',
'lastPerson',
'personByName'
]),
}
}

Mutations

After specifying what we store and how we access it, it’s time to change the state. Mutations are the only way to change the state. Actions also change the state but, they have to call relevant mutation. The difference between Mutations and Actions is that mutations are synchronous, actions are asynchronous.

  • Use Actions when you call an API to get resources or when you write a set-timeout function.
mutations: {
removeAll(state){
state.people = [];
},
addPerson(state,person){
state.people.push(person);
},
changeAgeByName(state, personUpdate){
state.people.forEach(element => {
if(element.name == personUpdate.name){
element.age = personUpdate.newAge
}
});
}
},
this.$store.commit('addPerson', person);       this.$store.commit('removeAll');
this.$store.commit("changeAgeByName", { name : "Jack", newAge : 5});
this.$store.commit(
{ type : "changeAgeByName", // Mutation name
name : "Jack", // additional arguments
newAge : 5}); // addition
al arguments.

Actions

In the same way, we can define actions in the actions section of the store object. One of the important things is, you have to call commit with relevant mutation when writing an action.

actions: {
removeAll (context) {
context.commit('removeAll')
},
addPerson(context, person){
context.commit('addPerson', person)
}
},
this.$store.dispatch('removeAll');
this.$store.dispatch('addPerson', person);
actions: {
removeAll (context) {
setTimeout(()=>{
context.commit('removeAll')
},1000);
},
getPerson(context){
axios.get('https://someurl/person')
.then(response => {
let person = response.data
context.commit('addPerson', person)
})
}
},
actions: {
removeAll ({commit}) {
commit('removeAll')
},
addPerson({ commit }, person){
commit('addPerson', person)
}
},

Modules

In software design, it’s good to create pieces(modules) for creating a better structure. Each piece has its responsibility for its job and has no access to the part that is not its job to access. That’s why we use modules in a Vuex application. Store object has modules property which can take zero to many different store objects.

modules: {
moduleA,
moduleB
},
namespaced: true,
state: {
people : [
{ name: 'Kate', age: 30 },
{ name: 'Jack', age: 34 },
{ name: 'John', age: 53 },
]
},
... other properties.
this.$store.dispatch('person/addPerson', person); // person namespace, actions is addPersonthis.$store.dispatch('person/seller/addPerson', person) // person has seller module that contains addPerson actionmapGetters('person',[  // mapGetter with a namespace
'people',
'firstPerson',
'lastPerson',
'personByName'
]),

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store