Vuex Store
Vuex is a simple state management library for Vue js. It is very easy to use. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.
Install Vuex
npm install vuex --save
Initialize Vuex
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)
Store
Time to build a store. Les goooo
Create a store
export default new Vuex.Store({
state:{
// Current state of the application lies here.
},
getters:{
// Compute derived state based on the current state. More like computed property.
},
mutations:{
// Mutate the current state
},
actions:{
// Get data from server and send that to mutations to mutate the current state
}
})// You can assign a store to variable and export
export const store = new Vuex.Store({})
// Import the store
import { store } from '/path/to/file'
State
First thing in the store is state
state:{
name:'Alicia Vikander',
age:20,
dob:'20/08/1990'
}
In vuex the single source of truth is the store. So let's hear a truth from the store.
Access State
Accessing a state is simpler than every other library
You can read the state directly like 👇
store.state.name // Alicia Vikander
But don’t MUTATE the state like 👇
store.state.name = 'NOOOOOOO'
This will get the work done but in long run, you won’t know which component changed the truth so this makes difficult to debug and track.
So let's see how to do
Import a helper function mapState from vuex. This will create a computed getter function for us. Then spread the mapState object with the name of the properties you want to access into computed properties of the component.
If you don’t want to change the name of the property then go with this 👇
computed:{
...mapState(['name', 'age', 'dob'])
// Now you can read the name by using this.name
}
But if you want to change the name then you have to use an object like notation
computed:{
...mapState({
userName : state => state.name,
userAge: state => state.age,
userDob: state => state.dob
})
// Now you can read the name by using this.userName
}
Finally, the component looks like this 👇
<template>
<div>
Name: {{ name }}
Age: {{ age }}
Dob: {{ dob }}
</div>
</template><script>import { mapState } from 'vuex'export default {
name:'Profile',
computed:{
...mapState(['name', 'age', 'dob'])
// Now you can read the name by using this.name
}
}
</script>
Now we can use `this.age` to access the truth from the store.
But again we can’t mutate the state like `this.age=this.age+1`
So the question is why not? Let's see
You have no rights to change someone’s property even if you have them. So let's ask them to do. Let's ask here 👇
Mutation
Mutation is the only object which has a proper right to mutate the state.
Mutation looks like this 👇
updateName(state, name){
state.name = name
}
A mutation may have two arguments as state and payload.
State has the current state of an application.
Payload is an optional one, which will give the data to mutate.
So after adding mutation, the store look like this 👇
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({
state:{
name:'Alicia Vikander',
age:20,
dob:'20/08/1990'
},
mutations:{
updateName(state, name){
state.name = name
}
}
})
Invoke Mutation
If we have the reference to store object then we can call the mutation directly like these.
store.commit('updateName','Alicia')
Object-Style Commit
store.commit({
type: 'updateName',
name: 'Alicia'
})
We will use the store.commit() notation in a router and inside the store but in components, we have another way to invoke mutation
Inside a component, we will Import a helper function ‘mapMutations’ from vuex and spread that into methods to invoke a mutation
methods:{
...mapMutations(['updateName'])
}
// Now this.updateName('Alicia') will call the mutation in the store and update the state.
If you want to change the name then 👇
methods:{
...mapMutations({
editName: 'updateName'
})
}
// Now this.editName('Alicia') will call the mutation in the store and update the state.
Now the component looks like this 👇
<template>
<div>
Name: {{ name }}
Age: {{ age }}
Dob: {{ dob }}
</div>
</template><script>import { mapState, mapMutations } from 'vuex'export default {
name:'Profile',
computed:{
...mapState(['name','age','dob'])
},
methods:{
...mapMutations(['updateName'])
}
}</script>
But “Mutations Must Be Synchronous” So If you want data from sever then you have to create actions.
Actions
Actions can contain arbitrary asynchronous operations, action commits mutation after doing the asynchronous operation.
For instance, if you want user data before rendering then you have to call the action.
What actions will do
- Request the server for user data
- Receive response from the server and if data exists then mutate the state else throw an error
- After mutating the state the components associated with that state will be re-rendered by vue instance.
Action has two arguments context and payload
context has the reference for a store.
To mutate the state use context.mutate(‘updateName’ , ‘Alicia’ ) .
To read a state ‘context.state.name’.
The payload is the optional one, which will carry optional data to do actions.
getUserData(context,payload){
// Get the data from server
axios.get('www.api.yourdomain').then((response)=>{
// commit to the store to mutate the state
context.commit('loadUserData',response)
})
}
After adding actions to store 👇
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({
state:{
name:'Alicia Vikander',
age:20,
dob:'20/08/1990'
},
mutations:{
updateName(state, name) => {
state.name = name
},
loadUserData(state,payload){
state.name = payload.name;
state.age = payload.age;
state.dob = payload.dob;
}
},
actions: {
getUserData(context,payload){
// Get the data from server
axios.get('www.api.yourdomain').then((response)=>{
// commit to the store
context.commit('loadUserData',response)
})
}
})
Access actions
If you have reference to store then dispatch an action using 👇
store.dispatch('nameOfAction');
Inside the store and router, we use this method. In components we may use mapActions helper functions
<template>
<div>
Name: {{ name }}
Age: {{ age }}
Dob: {{ dob }}
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
name:'Profile',
computed:{
...mapState(['name','age','dob'])
},
methods:{
...mapMutations(['updateName']),
...mapActions(['getUserData'])
}
}
</script>
Now we can use this.getUserData() to dispatch an action
Getters
We need some computed functions in all components So we define all those functions inside this getters. Every function inside getters computes derived state based on store state.
It has two arguments state and getters
The state has current state values
getters are optional, all other getters can be used inside one getter function
getters:{
isAdult(state,getters){
return state.age >=18 ? true : false
}
}
Call getters
store.getters.isAdult;
Inside components use mapGetters helper function and spread that into the computed property.
<template>
<div>
Name: {{ name }}
Age: {{ age }}
Dob: {{ dob }}
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
name:'Profile',
computed:{
...mapState(['name','age','dob'])
...mapGetters(['isAdult'])
},
methods:{
...mapMutations(['updateName']),
...mapActions(['getUserData'])
}
}
</script
Now you can access the getter by this.isAdult
PS: mapMutations, mapActions have to be inside methods, and mapState, mapGetters have to be inside a computed property.
Computed
And If you have to change the computed property then you can use a set function for computed property
computed: {
name: {
// getter
get: () => {
return this.$store.name
},
// setter
set: (newValue) => {
this.$store.dispatch('updateName',newValue)
}
}
}
When you try to mutate the computed property then you will get an error saying no setter function is available for that computed property. So if you want to mutate the computed property then write a set function.
Flow of data in vuex

😈 The END 😈
