Skip to content

Vuex: Vue's State Management Pattern

Important Note: Pinia is now Vue's officially recommended state management library, providing a more concise API that better fits the Composition API style. The Vuex introduced in this chapter is the state management solution widely used in Vue 2 and early Vue 3 projects. Understanding Vuex's concepts is still very helpful for maintaining existing projects.

What is a "State Management Pattern"?

In a complex application, multiple components might share the same state (data). For example, user's login information, items in the shopping cart, etc. If multiple components all depend on the same state and all need to modify this state, then the data flow will become very chaotic and difficult to maintain.

State management pattern is the practice of extracting shared state from components and placing it into a global, centralized "Store" for management. This way, any component can read state from this store, or trigger an action to modify the state.

Vuex is a state management pattern library specifically developed for Vue.js applications. It uses centralized storage to manage the state of all components in the application and ensures that state changes in a predictable way according to corresponding rules.

Vuex Core Concepts

The core of every Vuex application is the Store. A store contains the following core parts:

1. State

State is the sole data source that drives the application, which can be understood as the data object stored in the store.

js
import { createStore } from 'vuex'

const store = createStore({
  state() {
    return {
      count: 0,
      user: null
    }
  }
})

In Vue components, you can access state via this.$store.state.count (in the Options API) or store.state.count (in the Composition API).

2. Getters

Sometimes we need to derive some state from the store's state, for example, filtering a list and calculating a total. This is where Getters are useful. You can think of getters as computed properties of the store.

js
const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos(state) {
      return state.todos.filter(todo => todo.done)
    },
    doneTodosCount(state, getters) {
      return getters.doneTodos.length
    }
  }
})

3. Mutations

The only way to change the state in a Vuex store is to commit a mutation. Mutations in Vuex are very similar to events: each mutation has a string event type (type) and a callback function (handler). This callback function is where we actually perform state changes, and it accepts state as the first parameter.

js
const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    increment(state) {
      // Change state
      state.count++
    },
    incrementBy(state, payload) {
      state.count += payload.amount
    }
  }
})

// Commit mutation in the component
store.commit('increment')
store.commit('incrementBy', { amount: 10 })

Important: Mutations must be synchronous functions. To ensure the traceability of state changes, any asynchronous operations should not be placed in mutations.

4. Actions

Actions are similar to mutations, with the following differences:

  • Actions commit mutations rather than directly changing state.
  • Actions can contain arbitrary asynchronous operations.
js
const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment')
      }, 1000)
    }
  }
})

// Dispatch action in the component
store.dispatch('incrementAsync')

Summary

Vuex makes the process of state changes clear, predictable, and debuggable by centrally managing shared state and forcing mutations to modify state. Although Pinia is the first choice for new projects, understanding Vuex's core concepts (State, Getters, Mutations, Actions) is still crucial for understanding modern frontend state management.

Content is for learning and research only.