loading...

Setting up Vuex (state management) with Vue CLI 3

abhisheksarmah profile image Abhishek ・3 min read

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

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);

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");

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);
    }
  }
});

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
  }
});

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();
      });
    }
  }
};

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");

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

Posted on by:

abhisheksarmah profile

Abhishek

@abhisheksarmah

Building things using Laravel and Vue Js. Love to cook in my free time. Currently, I am starting to write blogs.

Discussion

markdown guide