Managing State With Vuex in Vue.js
State management is something you will ultimately have to deal with as you create increasingly complex frontend applications. Thankfully, with the help of Vuex, this isn’t as hard as you may think!
Installation
In order to install vuex
, you will have to use either yarn
or npm
like so:
## Npm
$ npm install vuex
## Yarn
$ yarn add vuex
Setting up Vuex
Once you have successfully installed Vuex in your VueJS application, you can set
your application to use it by doing the following within your main.js
file:
import Vue from "vue";
import Vuex from "vuex";
import App from "./App";
import router from "./router";
// Import the store from the file we are about to create
import { store } from "./store/index.js";
Vue.config.productionTip = false;
Vue.use(Vuex);
/* eslint-disable no-new */
new Vue({
el: "#app",
// tell our vue instance to use our store
store: store,
router,
components: { App },
template: "<App/>"
});
We then have to define our /src/store/index.js
file which will contain our
Vuex.Router()
object which we’ve imported and used in our main.js
file
above.
Core Concepts
So, there are 5 core concepts you will have to become familiar with if you wish
to use vuex
as your application’s state management system.
State
State is the object representation of your applications state. This could be as simple as this if we wanted to store a ’name’ value within our application:
import Vuex from "vuex";
import Vue from "vue";
export const store = new Vuex.Store({
state: {
name: "elliot"
}
});
If we wanted to make it more complex then we simply need to expand out our state object to store everything we need. This could be arrays, boolean values, nested objects or any of the 5 primitives types within JavaScript.
Mutations
Mutations within the vuex
world allow us to update the state
of our
application. These are very similar to event handlers and each mutation has a
string type and a handler.
Effectively, if you wished to update the name
within our state
object above,
you could do so through a mutation
. This mutation
has to be invoked through
the use of an action
which we’ll cover in the next section.
Let’s have a look at how we would create a updateName
mutation which would
allow us to change our name
value within our state
object:
import Vuex from "vuex";
import Vue from "vue";
export const store = new Vuex.Store({
state: {
name: "elliot"
},
mutations: {
updateName(state, newname) {
state.name = newname;
}
}
});
Actions
Actions allow us to commit
mutations. What this means is that should we wish
to update the name
of our state
object above, we would trigger an action
using the store.dispatch()
method and passing in the string name of the action
we wish to call.
The main reason we have this level of abstraction away from our mutations
is
so that we can make asynchronous requests. All mutations have to be synchronous,
so by having our actions
perform any asynchronous code and then commit
-ing
the result to a mutation, we manage to get round this.
import Vuex from "vuex";
import Vue from "vue";
export const store = new Vuex.Store({
state: {
name: "elliot"
},
mutations: {
updateName(state, newname) {
state.name = newname;
}
},
actions: {
updateName({ commit }) {
commit("updateName", "Sophie");
}
}
});
Whenever we trigger the updateName
action, the name
stored within our
state
object will subsequently be updated to Sophie
.
We can trigger an action
by doing the following:
store.dispatch("updateName");
Due to the way we have registered our vuex
store within our application, you
can typically trigger this like so:
this.$store.dispatch("updateName");
Getters
There are some situations where we need to get compute a derived state based on
stored state. For example, say we wanted the first initial of our name
value
that we have already stored, we could define a Getter
that would compute this
for us, cache the result and then return the result.
This caching is a major benefit and can help us to improve the performance of
our application. Getters
also refresh the cached result should any of the data
that our result dependes upon be changed.
For example, if we had a name
set to elliot
originally, and we had a
getter
that returned e
as the first initial, this e
result would be cached
for us. However, when we update the name by dispatching an action
, this result
would be updated to S
as that would be the initial of Sophie
.
import Vuex from "vuex";
import Vue from "vue";
export const store = new Vuex.Store({
state: {
name: "elliot"
},
mutations: {
updateName(state, newname) {
state.name = newname;
}
},
actions: {
updateName({ commit }) {
commit("updateName", "Sophie");
}
},
getters: {
firstInitial: state => {
return state.name[0];
}
}
});
If you are doing more expensive operations such as filtering a large list of objects then this starts to become more beneficial.
Conclusion
Hopefully, you found this tutorial on vuex
useful and it showed you everything
you need in order to get started using it within your own Vue.js applications.
Further Reading
If you enjoyed this article then you may enjoy some of the other tutorials on our site: