Complete Guide to Vuex Store: Everything You Need to Know

Vuex is a library that allows us to share data/state between our Vue.js components easily. In this article, we will set up the store and see how to use it with a Vue 2 application. A store is a global object that holds the state of an application. It is mainly used for managing data, but can also be used for other things.

Installing Vuex

Install the Vuex store with version 3 for Vue 2, if you use Vue 3 please prefer to install Vuex 4 instead.

npm install vuex@3 

Setup Vuex store

In your ./src folder create a folder name store to hold the Vuex store. Structure your Vuex store as below:

./src/store/modules/
./src/store/
           /actions.js
           /getters.js
           /mutations.js
           /state.js
           /index.js

This is the main action of the Vuex store.

In ./src/store/actions.js

export default {
};

This is the main getter of the Vuex store.

In ./src/store/getters.js

export default {
};

This is the main mutation of the Vuex store.

In ./src/store/mutations.js

export default {
};

This is the main state of the Vuex store.

In ./src/store/state.js

export default {
};

Load the main store and modules into index.js.

In ./src/store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';

Vue.use(Vuex);

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

Integrate Vuex store to Vue

After setup, all the necessary required for Vuex store also it modules and load to the index.js now integrate it to your Vue application by importing it to the main.js. We will also need a router in order to load the page checkout this article VueJs - Setting up Vue Router.

In ./src/main.js

import Vue from 'vue';
import App from './App.vue';
import router from './routes';
import store from './store';

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app');

Use Vuex state

This is a sample of the Vuex state usage declaration and map state into a Vue component.

In ./src/store/state.js

export default {
  title: 'HelloWorld',
};

Used state in component with map state

<template>
  <div>
    <p>Map state</p>
    <p>{{ title }}</p>
  </div>
</template>

<script>
import { mapState } from 'vuex';
export default {
  computed: {
    ...mapState(['title']),
  },
};
</script>

Use Vuex getters

In Vuex getters are the same as a Vue computed one computed state data and one computed component data. In this example, we will create a state posts data and use getters to get only the visible posts.

In ./src/store/state.js

export default {
  posts: [
    { title: 'Post 1', visible: true },
    { title: 'Post 2', visible: false },
  ],
};

In ./src/store/getters.js

export default {
  getVisiblePosts({ posts }) {
    return posts.filter((post) => post.visible);
  },
};

Used getters in components with map getters

<template>
  <div>
    <p>Map getters</p>
    <p>{{ getVisiblePosts }}</p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex';
export default {
  computed: {
    ...mapGetters(['getVisiblePosts']),
  },
};
</script>

Use Vuex mutations and Vuex actions

Create a posts state to hold an array of post data.

In ./src/store/state.js

export default {
  posts: [],
};

Create mutations setPosts to set posts data from actions.

In ./src/store/mutations.js

export default {
  setPosts(state, payload) {
    state.posts = payload;
  },
};

Create actions fetchPosts that fetch posts data from the fake promise and return data then we set it to posts state by mutation setPosts.

In ./src/store/actions.js

export default {
  async fetchPosts({ commit }) {
    const dummyDataFromAPI = await new Promise(
      (resolve) =>
        setTimeout(() => resolve([{ title: 'Post 1' }, { title: 'Post 2' }])),
      500
    );
    commit('setPosts', dummyDataFromAPI);
  },
};

Used actions in component with map actions

<template>
  <div>
    <p>Used mutations with actions</p>
    <p>{{ posts }}</p>
  </div>
</template>

<script>
import { mapActions, mapState } from 'vuex';
export default {
  computed: {
    ...mapState(['posts']),
  },
  methods: {
    ...mapActions(['fetchPosts']),
  },
  async created() {
    await this.fetchPosts();
  },
};
</script>

Use Vuex as a module

As you can see in the example above the state posts we used in a main state to avoid things getting too complicated we can break it down by a module. In this case, we can put it in a post module.

Create a post module.

In ./src/store/modules/post.js

export default {
  namespaced: true,

  state: () => ({
    posts: [],
  }),
  getters: {},
  mutations: {
    setPosts(state, payload) {
      state.posts = payload;
    },
  },
  actions: {
    async fetchPosts({ commit }) {
      const dummyDataFromAPI = await new Promise(
        (resolve) =>
          setTimeout(() =>
            resolve([
              { title: 'Post 1' },
              { title: 'Post 2' },
              { title: 'Post 3' },
            ])
          ),
        500
      );
      commit('setPosts', dummyDataFromAPI);
    },
  },
};

Add Vuex post module to Vuex store

In ./src/store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';

import post from './modules/post';

Vue.use(Vuex);

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

Used Vuex module in component

The same as normal usage for the module you just need to specify the module name before the map entity.

<template>
  <div>
    <p>Used Vuex as a module</p>
    <p>{{ posts }}</p>
  </div>
</template>

<script>
import { mapActions, mapState } from 'vuex';
export default {
  computed: {
    ...mapState('post', ['posts']),
  },
  methods: {
    ...mapActions('post', ['fetchPosts']),
  },
  async created() {
    await this.fetchPosts();
  },
};
</script>