In a large Vue application it is inevitable that you run into the problem of different components having to use the same variable. To make this work you often have to pass the same variable between a lot of components. Variables are being passed from component to component all the way down the tree, which makes your code an unreadable mess. If you continue with this long enough, you will reach a certain point where managing state gets very complex.

Vuex

The solution, ofcourse, is Vuex. Vuex is a state management library for Vue.js applications. At the center of every Vuex application is a store, which basically is a container that holds the state of the application.

When using Vuex, components use the same data source. This means that there is a single source of truth. Without Vuex, components could have their own version of state.

In this article I will show you how to setup a Vuex store and how you can use this store within the Vue components. I will be starting from scratch with a new Vue project.

Installation

To use Vuex within our Vue application we have to install it first:

npm install vuex --save

Creating the store

Folder structure

The store that we are going to create will have its own folder. So let’s start by creating a store folder in the src folder. A store can contain multiple modules, which I prefer to store in their own folder. Create a new folder called modules in the store folder that you have just created. In the modules folder we will create another folder called products , which will manage the state for the products in our application.

Store index

In the store folder we will create a file called index.js . This file contains the definition of our store. As you can see the modules get imported into the store.

Modules

All state of your Vue application is contained inside one object. This can get really big as your application grows. Luckily, Vuex allows you to divide the store into modules. Each module containing its own state, getters, actions and mutations.

A module has the following files:

index.js

getters.js

actions.js

mutations.js

index.js

index.js is where the state of the module gets defined. Furthermore, this file bundles the getters, actions and mutations into an object that represents the module.

I prefer my modules to being namespaced. By default, everything inside a module is registered under the global namespace. This allows multiple modules to react to the same mutation or action. I don’t like this default behaviour, so I chose for namespaced = true; in the modules. This way the modules are more self-contained.

As you can see in the example the state is just an object with some properties for the products module.

State is nothing more than an object that needs to be shared within the application.

mutations.js

The mutations.js file contains all the mutation functions. Mutations, as the name says, are responsible for mutating the state.

Mutations are the only way to makes changes to your state

In Vuex the first argument of a mutation function always is the state object.

actions.js

The actions.js file contains all the action functions. Actions are like mutations, but they don’t mutate the state. Actions commit mutations. Furthermore, actions can contain asynchronous operations.

In this example we have two actions that both commit a mutation. The addProducts action commits the addProduct mutation, which we will use later on.

In the example that we are going to create we won’t be using the getProducts action. I created this action as an extra (asynchronous) example of what an action can look like. The getProducts action sends a request to an API and commits a mutation based on the response.

getters.js

getters.js contains all the getter functions. Getters are for a store what computed properties are for a component. Getters have access to the state aswell, via the first parameter.

Using the store in a component

Before we can start using the store in a component, we have to inject the store into all child components from the root component. We do this in main.js , where our Vue instance gets created.

Note:

You can remove line 4, 5 and 7 since you won’t need axios for this example. If you would like to use axios, you will need to install it:

npm install --save axios vue-axios

The components

To demonstrate how the store works with components, we are going to create three components in the components folder:

ProductForm.vue

ProductList.vue

InStockList.vue

ProductForm.vue

This component has a form that will dispatch an action to the store to add a product once the button gets clicked. As you can see on line 29 we dispatch an action to the store. Since we namespaced the module we have to prefix the action name with the name of the module.

ProductList.vue

The ProductList component contains a list of all products, both in stock and not in stock. The list will only be displayed if the list of products is not empty.

Note that the products variable is coming from the state object. We use the mapState helper for this. This helper generates computed getter functions for us.

Since we namespaced the module we need to pass the name of the module as the first argument. The second argument is the list of properties that we want to create the getter functions for.

We use the spread operator (…) so that we are able to mix local computed properties with the object that mapState returns.

InStockList.vue

Just like the ProductList component, this component contains a list of products. The difference being that this component only shows products that are in stock. It uses the inStock getter function from the store for this. This function applies a filter on the products variable that is in the state.

Note that the mapGetters function is used in exactly the same way as the mapState function.

Let’s see it in action!

Now that we have created the store and the components it is time to see our code in action.

Since we use the same state property for both list components, both list components should react to a change of the products property. This change will be triggered by adding a product.

Our code in action!

State in the Vuex store

As you can see in the image above adding a product updates the state, which will cause the list components to update.