DEV Community

Abhishek
Abhishek

Posted on

Setting up Vuex (state management) with Vue CLI 3

This article explains how to set up Vuex in a Vue CLI 3 project. It is really helpful while you are managing user's state when authenticating a Vue application.

Steps to follow -

Install Vuex

First step is to install Vuex via npm or yarn

# Using npm
npm install vuex --save

# Using Yarn
yarn add vuex
Enter fullscreen mode Exit fullscreen mode

Add Vuex to your application

When used with a module system, you must explicitly install Vuex via Vue.use()

//main.js
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);
Enter fullscreen mode Exit fullscreen mode

Creating store object to use in Vue App

After installing Vuex, let's create a store. It is pretty straightforward - just provide an initial state object, and some mutations:

//main.js
// Make sure to call Vue.use(Vuex) first if using a module system
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  }
});
// Make sure to inject the store in the vue instance
new Vue({
  store,
  render: h => h(App)
}).$mount("#app");
Enter fullscreen mode Exit fullscreen mode

Due to using a single state tree, all state of our application is contained inside one big object. However, as our application grows in scale, the store can get really bloated.

Vuex allows us to divide our store into modules. Each module can contain its own state, mutations, actions, getters, and even nested modules. For any reference, please checkout this guide

Extracting store into individual file

Now create a index.js file in src/store/index.js and add

//index.js
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    errors: {}
  },

  getters: {
    errors(state) {
      return state.errors;
    }
  },

  mutations: {
    SET_ERRORS(state, data) {
      state.errors = data;
    }
  },

  actions: {
    setErrors({ commit }, errors) {
      commit("SET_ERRORS", errors);
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

Using vuex modules

Our updated index.js file will look like

//index.js
import Vue from "vue";
import Vuex from "vuex";

// importing a vuex module
// imporing the auth module which handles the user authentication
import auth from "./auth";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    errors: {}
  },

  getters: {
    errors(state) {
      return state.errors;
    }
  },

  mutations: {
    SET_ERRORS(state, data) {
      state.errors = data;
    }
  },

  actions: {
    setErrors({ commit }, errors) {
      commit("SET_ERRORS", errors);
    }
  },
  modules: {
    //registering the auth module that is imported
    auth
  }
});
Enter fullscreen mode Exit fullscreen mode

This blog post example uses graphql client for autenticating the users. If you are using axios as a http client, then your vuex actions might look different than this. The auth.js file will look like

//auth.js
import {
  LOGIN_USER_MUTATION,
  GET_CURRENT_USER,
  LOGOUT
} from "../graphql/queries/userQueries";
import { Apollo } from "../graphql/apollo";

export default {
  namespaced: true,
  state: {
    token: null,
    user: null
  },
  getters: {
    authenticated(state) {
      return !!state.token && !!state.user;
    },
    user(state) {
      return state.user;
    }
  },
  mutations: {
    SET_TOKEN(state, token) {
      state.token = token;
    },
    SET_USER(state, data) {
      state.user = data;
    }
  },
  actions: {
    async login({ dispatch }, credentials) {
      let response = await Apollo.mutate({
        mutation: LOGIN_USER_MUTATION,
        variables: {
          username: credentials.email,
          password: credentials.password
        }
      });

      return dispatch("attempt", response.data.login.access_token);
    },
    async attempt({ commit, state }, token) {
      if (token) {
        localStorage.setItem("token", token);
        commit("SET_TOKEN", token);
      }
      if (!state.token) {
        return;
      }
      try {
        let response = await Apollo.query({
          query: GET_CURRENT_USER
        });
        commit("SET_USER", response.data.me);
        Apollo.resetStore();
      } catch (e) {
        localStorage.removeItem("token");
        commit("SET_TOKEN", null);
        commit("SET_USER", null);
        Apollo.resetStore();
      }
    },

    logout({ commit }) {
      return Apollo.mutate({
        mutation: LOGOUT
      }).then(() => {
        // console.log(store);
        localStorage.removeItem("token");
        commit("SET_TOKEN", null);
        commit("SET_USER", null);
        Apollo.resetStore();
      });
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

Import the file in your Vue app(main.js)

Now our updated main.js file will look like

//main.js
import Vue from "vue";
//import the store module
import store from "@/store";

// Make sure to inject the store in the vue instance
new Vue({
  store,
  render: h => h(App)
}).$mount("#app");
Enter fullscreen mode Exit fullscreen mode

That’s it! Now restart your Vue CLI project and it should all work fine. Checkout Official Vuex docs for more information.

Discussion (1)

Collapse
brojenuel profile image
Jenuel Oras Ganawed

I think this tutorial is about vue 2 not vue 3. Vue 3 uses the createApp function