Vuex in Vue.js

26th October 2021


Page Index


    Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.

    What is a "State Management Pattern"?

    Let's start with a simple Vue counter app:

    new Vue({
      // state
      data () {
        return {
          count: 0
      // view
      template: `
        <div>{{ count }}</div>
      // actions
      methods: {
        increment () {

    It is a self-contained app with the following parts:

    • The state, the source of truth that drives our app;
    • The view, a declarative mapping of the state;
    • The actions, the possible ways the state could change in reaction to user inputs from the view.

    This is an simple representation of the concept of "one-way data flow":

    However, the simplicity quickly breaks down when we have multiple components that share a common state:

    • Multiple views may depend on the same piece of state.
    • Actions from different views may need to mutate the same piece of state.

    So to overcome this problem an approach is choosen

    why don't we extract the shared state out of the components, and manage it in a global singleton? With this, our component tree becomes a big "view", and any component can access the state or trigger actions, no matter where they are in the tree!
    This is the basic idea behind Vuex.

    Getting Started

    At the center of every Vuex application is the store. A "store" is basically a container that holds your application state. There are two things that make a Vuex store different from a plain global object:

    • Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes.
    • You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations.
    • This ensures every state change leaves a track-able record, and enables tooling that helps us better understand our applications.

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

    // Make sure to call Vue.use(Vuex) first if using a module system
    const store = new Vuex.Store({
      state: {
        count: 0
      mutations: {
        increment (state) {

    Now, you can access the state object as store.state, and trigger a state change with the store.commit method:

    console.log(store.state.count) // -> 1

    Lets dig into some core concepts of Vuex


    Vuex uses a single state tree - that is, this single object contains all your application level state and serves as the "single source of truth". This also means usually you will have only one store for each application.

    Getting Vuex State into Vue Components

    Since Vuex stores are reactive, the simplest way to "retrieve" state from it is simply returning some store state from within a computed property:

    // let's create a Counter component
    const Counter = {
      template: `<div>{{ count }}</div>`,
      computed: {
        count () {
          return store.state.count

    Whenever store.state.count changes, it will cause the computed property to re-evaluate, and trigger associated DOM updates.


    The only way to actually change state in a Vuex store is by committing a mutation. Vuex mutations are very similar to events: each mutation has a string type and a handler. The handler function is where we perform actual state modifications, and it will receive the state as the first argument:

    const store = new Vuex.Store({
      state: {
        count: 1
      mutations: {
        increment (state) {
          // mutate state

    You cannot directly call a mutation handler. Think of it more like event registration: "When a mutation with type increment is triggered, call this handler." To invoke a mutation handler, you need to call store.commit with its type:


    3. Actions

    Actions are similar to mutations, the differences being that:

    • Instead of mutating the state, actions commit mutations.
    • Actions can contain arbitrary asynchronous operations.

    Let's register a simple action:

    const store = new Vuex.Store({
      state: {
        count: 0
      mutations: {
        increment (state) {
      actions: {
        increment (context) {

    Dispatching Actions

    Actions are triggered with the store.dispatch method:


    Application Structure

    Vuex doesn't really restrict how you structure your code. Rather, it enforces a set of high-level principles:

    1. Application-level state is centralized in the store.
    2. The only way to mutate the state is by committing mutations, which are synchronous transactions.
    3. Asynchronous logic should be encapsulated in, and can be composed with actions.

    As long as you follow these rules, it's up to you how to structure your project. If your store file gets too big, simply start splitting the actions, mutations and getters into separate files.

    For any non-trivial app, we will likely need to leverage modules. Here's an example project structure:

    ├── index.html
    ├── main.js
    ├── api
    │   └── ... # abstractions for making API requests
    ├── components
    │   ├── App.vue
    │   └── ...
    └── store
        ├── index.js          # where we assemble modules and export the store
        ├── actions.js        # root actions
        ├── mutations.js      # root mutations
        └── modules
            ├── cart.js       # cart module
            └── products.js   # products module

    About the Author

    Related Blogs

    View All Blogs
    No blogs!

    Want #swag?

    Join our monthly raffle!

    Every month, One Lucky Duck gets free swag shipped to their doorstep, wherever in the world you are! All you have to do is join our Discord channel today and tweet about the amazing things we do. #nullcast #luckyduck

    We will announce the winners on Twitter and through our discord channel.