Simple Guide to Vuex (with Vue.js)

February 9, 2020

Why use Vuex

  • The general advice is don’t use Vuex until you think you need it
  • If you think Vuex is too heavy for your needs, try store pattern
  • Vuex is a centralize storage, meaning multiple components can access the same storage, and it could be accessed outside of components as well
  • Vuex consist of state (the data), getters (computed state), mutations (function to modify the state) and actions (async functions to fetch data and commit mutations).

My use case for Vuex is I was building a SPA with multiple pages of content with SSR as well based on this sample.

  • Vuex is useful to preload the data/state before the component is rendered
  • When I am switching pages/components, I can reuse the data/state as cache to avoid fetching data from server again
  • Actions is nice as a repository of code how the data/state is filled, decouple the fetch code from components.

Setup

Install

npm install vuex --save

Setup

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

Vue.use(Vuex)

Usage

import store from './store'

const app = new Vue({
  // router, // optional
  store, // to allow this.$store access in component
  render: h => h(App)
})

Create

Create src/store/index.js.

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

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0,
    home: null,
    homePages: {}
  },
  mutations: {
    increment (state) {
      state.count++
    },
    setHome(state, data) {
      state.home = data
    },
    setHomePage(state, { id, data }) {
      Vue.set(state.homePages, id, data)
    }
  },

  actions: {
    fetchFileHashes({ commit, state }) {
      return new Promise((resolve, reject) => {
        if (!state.fileHashes) {
          fetch('/data/hash.json', {cache: 'no-cache'}).then(response => response.json()).then(data => {
            commit('setFileHashes', data)
            resolve(data)
          })
        }
        else {
          resolve(state.fileHashes)
        }
      })
    },
    // example via callback
    fetchHome({ commit }) {
      fetch('/data/home.json').then(response => response.json()).then(data => {
        commit('setHome', data)
      })
    },
    // example via async
    async fetchHomePage({ dispatch, commit, state }, id) {
      const response = await fetch(`/data/page-${id}.json`)
      const data = await response.json()
      commit('setHomePage', {id, data})
    }
  }
})

export default store

You can update store from outside of component.

import store from './store'

store.commit('increment')

const count = store.state.count

Components

Call vuex in components

export default {
  computed: {
    home() {
      return this.$store.state.home
    },
    homePage1() {
      return this.$store.state.homePages[1]
    }
    count() {
      return this.$store.state.count
    }
  },
  created() {
    this.$store.commit('increment')   // commit for mutation
    this.$store.dispatch('fetchHome') // dispatch for action
    this.$store.dispatch('fetchHomePage', 1)
  }
}
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.