A guide to state management in Vue JS with Vuex

Get your vuejs application state managed with vuex

If your Vue.js application grows bigger and consists of multiple components you might run into the problem of how to share data across the those components and make sure that components which are using the same data are always updated if data is changing.   To solve that problem you can use Vuex which makes it possible to use a centralized state management in your application. Vuex is a library which helps you to enforce a Flux-like application architecture in your Vue.js 2 application.   So what exactly is meant by state and centralized state management? Simply, you can think of state as just data you use in your application. So a centralized state is just data you’re using by more than one component (application level state).   Vuex introduces a centralized state management by implementing the following core concepts (Store concept):
  • State Tree: An object containing the data
  • Getters: Used to access data from the state tree of the store
  • Mutations: Handler functions that perform modifications of data in the state tree
  • Actions: Functions that commit mutations. The main difference to Mutations is that Actions can contain asynchronous operations
Don’t worry if this concept seems a little bit strange at first. We’ll explore the various building blocks in detail in the following. Take a look at this diagram form the Vuex docs:
This overview is great for understanding the flows of actions and data in the store concept. From the diagram you can see that the data flow is unidirectional.

A Vue component initiates a state change by dispatching an Action. The Action method can be used to perform asynchronous operation (e.g. accessing a web service to retrieve data) and then commit a Mutation. The Mutation performs the modification of the state tree. A new state becomes available is used by components to display the changed data.
. . .

Setting Up A Vue.js 2 Project And Installing Vuex

The easiest way to set up a new Vue.js 2 project is to use Vue CLI. To install Vue CLI on your system use the following command:
$ npm install --global vue-cli

Now we're ready to use the vue command to initiate a new Vue project:
$ vue init webpack vuex-test-01

Next, change into the newly created project folder:
$ cd vuex-test-01
 Use NPM to install the default dependencies
$ npm install
 Finally you can start up the development web server by using the npm command in the following way:
$ npm run dev
 In the next step we need to add the Vuex library to the project.  Vuex is an official Vue package, but not part of the core library. If you want to use Vuex in your project, you first need to install it via NPM:
$ npm install vuex --save
 This makes sure that this package is downloaded in the node_modules folder of the project and that this dependency is added to package.json file.

Setup Vue and Vuex

Assuming you have an existing Vue starter app that looks like the example below:
const App = new Vue({ template: ` <div>Hello</div> ` }); App.$mount('#app');

When working with Vue and Vuex via script imports, Vuex automatically sets itself up. If using the module system, then you need to install Vuex:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)


Creating A Store

Having installed Vuex, we’re now ready to create a first store in our application. Within the src folder create a new subfolder named store. Within that folder create a new file store.js and insert the following code:
const store = new Vuex.Store({ state: { count: 0 } })

In order to have access to this store via the Vue instance, you need to tell Vue about it:
const App = new Vue({ template: ` <div>Hello</div> `, // Configure store store: store }); App.$mount('#app');


Rendering Store State

Vuex state is reactive. Therefore, you can treat it like the usual reactive object returned from a data function. We can use the computed member property to retrieve values:
... var App = new Vue({ computed: { counter: function() { return this.$store.state.counter } }, template: ` <p class="counter">{{counter}}</p> `, store: store });

The computed counter can then be bound to the template using interpolation.


Store Getters

We will violate DRY when more than one component depends on a computed value because we will have to compute for each component. Therefore, it's best to handle computation inside the store using the getters property:
const store = new Vuex.Store({ state: { counter: 0 }, getters: { counter: state => state.counter * 2 } }) var App = new Vue({ computed: { counter: function() { return this.$store.getters.counter } }, template: ` <p class="counter">{{counter}}</p> `, store: store });

Store Mutations

Mutations are synchronous functions that are used to update state. State must not be updated directly, which means this is incorrect:
increment () { this.$store.state.counter++ }

The state changes must be done via mutation functions in the store:
const store = new Vuex.Store({ state: { counter: 0 }, ... mutations: { // Mutations increment: state => state.counter++ } })

Mutations are like events. To call them, you have to use the commit method:
methods: { increment: function () { this.$store.commit('increment') }, }, template: ` <div> <p class="counter">{{counter}}</p> <div class="actions"> <div class="actions-inner"> <button @click="increment">+</button> </div> </div> </div> `,


Summary

If your Vue application grows bigger and consists of multiple components which needs to share data, introducing a central state management might be the right approach for you project. By using the Vuex library it’s easy to implement central state management in your Vue app by introducing a central store in your application.   With this tutorial you’ve gained a basic overview about the centralized state management concept and you’ve learned how to apply Vuex in your application. In one of the next tutorials we’ll use that knowledge and dive deeper into that topic by implementing a real-world Vue.js application with Vuex.

It's not the same without you

Join the community to find out what other Ednsquare users are discussing, debating and creating.