Vue.js 2|3 Vuex State Management Tutorial by Example

Last updated on by Digamber
Vue is an excellent open-source front-end library to build user-friendly web/mobile applications. It follows the same component-based architecture as other popular frameworks do.

In this tutorial, we are going to understand how to manage state when the size of the application starts expanding. Assume if you have more than 100 components or more than that, and you have to manage the data that goes from one component to another component.

Vue offers the Vuex State Management library that does the job for us. In this tutorial, we will understand how we can work with the Vuex library to manage the state via the store.

What is Vuex according to its official source.

Vuex is a state management pattern + library for Vue.js applications. 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.
Vuex

Vuex State Management Example for Vue.js

We will learn how to set up a Vuex store to manage the states among Vue components. We will create a basic app in which we will make the API call to fetch components from the fake json server and store the products in the Vuex store.

Setup Vue and Vuex

I already assume you have already installed node and vue cli in your development machine. Run the following command to create a new vue.js project from scratch.

vue create vue-state-mgmt

We can automatically configure Vuex store by choosing the option at the time of installing the fresh new vue app.

? Check the features needed for your project: 
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◉ Vuex
 ◉ CSS Pre-processors
 ◉ Linter / Formatter
❯◯ Unit Testing
 ◯ E2E Testing

If we select Vuex then the Vuex store will be set up by default with the vue app.

Configure Vuex Store in Vue

Create JSON Server

We need to set up a fake JSON server in order to make the API calls.

Type the following command in the terminal to install the json-server.

npm install -g json-server

Create database.json file at the root of the project and also populate some data into it.

{
    "users": [
        {
            "id": 1,
            "name": "Leanne Graham",
            "email": "Sincere@april.biz"    
        },
        {
            "id": 2,
            "name": "Ervin Howell",
            "email": "Shanna@melissa.tv"
        },
        {
            "id": 3,
            "name": "Clementine Bauch",
            "email": "Nathan@yesenia.net"
        }        
    ]     
}

Start the JSON server.

json-server --watch database.json

You can verify you API on the following URL:

http://localhost:3000/users

http://localhost:3000/users/1

Creating & Managing State via Vuex Store

You can create a store by creating an instance of Vuex’s Store and passing in our store details as object:

The Vuex library offers the centralized store for managing the state for Vue.js components. It is responsible for getting and updating the state of every value which are declared using the Vuex library.

Create modules/user-module.js file and paste the below code in it.

import axios from 'axios'

const state = { 
    users: []
};

const getters = { 
    usersList: state => state.users
};

const actions = { 
    async fetchUsers({commit}){
      const response = await axios.get("http://localhost:3000/users");
      commit("setUsers", response.data)
    },
    async addUsers({commit}, user){
      const response = await axios.post("http://localhost:3000/users", user);
      commit("addNewUser", response.data)
    },
    async deleteUser({commit}, id){
      await axios.delete(`http://localhost:3000/users/${id}`);
      commit("removeUser", id)
    }
};

const mutations = { 
    setUsers: (state, users) => (
        state.users = users
    ),
    addNewUser: (state, user) => state.users.unshift(user),
    removeUser: (state, id) => (
        state.users.filter(user => user.id !== id),
        state.users.splice(user => user.id, 1)
    )
};

export default {
    state,
    getters,
    actions,
    mutations
}

Import the userModule in store/index.js file.

import Vue from 'vue'
import Vuex from 'vuex'
import UsersModule from '../store/modules/users-module'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
    UsersModule
  }
})

state: Vuex manages a single state tree – this single object includes all your application-level state and serves as the “single source of truth”. This also means usually, you will have only one store for each application.

getters: Vuex allows us to define “getters” in the store. They work as a computed property for stores. The same computed properties, a getter’s outcome is cached based on its dependencies, and will solely re-evaluate when some of its dependencies have changed.

actions: The action handlers are used to make API calls that is used to perform the CRUD operations to manage the data for the Vuex store. Action handlers get a context object which reveals the same set of methods and properties on the Vuex store instance.

mutations: As the name suggests it is responsible for mutating the state of the store object, we can easly update Vuex state. The exclusive approach to actually update state in a Vuex store is by performing a mutation. Vuex mutations are related to events: each mutation has a string type and a handler.

Adding Vuex Store in Vue Components

In this step, we are going to add the Vuex store in vue components and mange the the data in Vue state.

Add the following code inside the components/AddUser.vue file.

<template>
 <form @submit.prevent="onUserSubmit">
  <div class="form-group">
    <input type="text" class="form-control" placeholder="Enter name" v-model="name">
  </div>
  <div class="form-group">
    <input type="text" class="form-control" placeholder="Enter email" v-model="email">
  </div>
  <button type="submit" class="btn btn-block btn-primary">Add</button>
</form>
</template>

<script>
import { mapActions } from "vuex";

export default {
  name: 'AddUser',
  data(){
      return {
        name: '',
        email: ''
      }
  },
  methods:{
    ...mapActions(["addUsers"]),
    onUserSubmit() {
        this.addUsers({
          name: this.name,
          email: this.email
        })
    }
  }
}
</script>

Let us display the users list in vue component. Include the following code inside the components/Users.vue.

<template>
  <div>
    <ul class="list-group mt-5">
      <li class="list-group-item list-group-item-action" v-for="user in usersList" :key="user.id">

        <div class="d-flex w-100 justify-content-between">
          <h3>{{user.name}}</h3>

          <small class="text-danger delete" @click="deleteUser(user.id)">&#10005;</small>
        </div>
        <p>{{user.email}}</p>

      </li>
    </ul>
  </div>
</template>

<script>
  import {
    mapGetters,
    mapActions
  } from "vuex";

  export default {
    name: 'Users',
    methods: {
      ...mapActions(["fetchUsers", "deleteUser"])
    },
    computed: mapGetters(["usersList"]),
    created() {
      this.fetchUsers()
    }
  }
</script>

<style>
 .delete {
   font-size: 18px;
   cursor: pointer;
 }
</style>

mapGetters: is a helper that allows formulating a computed property that displays the value returned by an assigned getter.

mapActions: is a helper that allows defining a method that would be comparable as calling dispatch on an action.

mapMutations: is a helper that helps create a method which will be similar as calling commit on a mutation.

Adding Vuex Store in Vue Components

Summary

So this was it, we have successfully developed a basic todo app in Vue and tried to shed light on the state management concept. We learned how to create a Vuex store that manages the data via state, getters, mutations and actions for the vue components. I believe this tutorial will surely help you out with the basic understanding of integrating Vuex stores in vue.

You can get the full code of this tutorial on GitHub.

Happy Coding!