Skip to main content

By Rachel Opperman

Intro to the Vuex Map Helpers

Are you sick of seeing this.$store everywhere in Vue components?

Vuex is an excellent tool for managing the state of a Vue application, but the syntax for accessing the Vuex store in components can be a bit cumbersome and repetitive. Who wants to have to use this.$store.state when accessing state properties, or this.$store.dispatch('<action_name>', <action_arguments>) when dispatching an action? I sure don't. If you'd also like to avoid that, read on to see how the Vuex map helpers can help us clean up the code in our components by removing repetitive syntax.

Introducing the Vuex map helpers

There are four Vuex map helpers, one for each "portion" of the store:

  • State
  • Getters
  • Actions
  • Mutations

In general, what they allow us to do is "map" parts of the store to either computed properties or methods in a component. These computed properties and methods can then be used throughout the component just like any other computed property or method that we create. Better yet, these helpers are included with vuex, so we don't have to add any separate packages in order to use them.

Kicking things off: the mapState helper

State properties are often used as computed properties in Vue components. For example, you may have seen or written code like this:

export default {
  computed: {
    user() {
      return this.$store.state.user
    }
  }
}

For one computed property, this probably doesn't seem like such a bad thing. But imagine that the component needs several such computed properties. In that case, such code quickly becomes repetitive.

The mapState helper can be used to reduce that repetition and clean up the component's code. When using mapState, the above code becomes the following:

import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState({
      user: state => state.user
    })
  }
}

The first thing we have to do is import mapState from vuex. Once that's done, we can use it in the computed object of the component. mapState returns an object, so the spread operator (...) is used to merge that object with the rest of the component's computed object.

Each key provided to mapState (user in the example) becomes the name of a computed property that can be used elsewhere in the component. The value provided to each key is an arrow function, with state as the argument, that returns a specific state property (again, user in the example).

If you're using Vuex modules, all you need to do is add in the module name. For example, if the user state is kept in a module named auth, then the key-value pair would become the following:

user: state => state.auth.user

A close cousin: the mapGetters helper

Much like state properties, Vuex getters are also often used as computed properties in a component. So, instead of using this.$store.<getter_name>, we can use the mapGetters helper similarly to how we used the mapState helper above. For example, the code below…

export default {
  computed: {
    completedTodoItems() {
      return this.$store.getters.completedTodoItems
    }
  }
}

...becomes the following:

import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters({
      completedTodoItems: 'completedTodoItems'
    })
  }
}

If you're using Vuex modules, then the module name, followed by a /, simply has to be placed in front of the getter name. For example, if the completedTodoItems getter is in the todos module, then the key-value pair becomes the following:

completedTodoItems: 'todos/completedTodoItems'

Accessing store actions with the mapActions helper

The main difference between the mapActions helper and the mapState and mapGetters helpers is that actions are mapped as methods, rather than as computed properties. Without the mapActions helper, an action would be dispatched in a component like so:

export default {
  methods: {
    addTodo(todo) {
      this.$store.dispatch('addTodo', todo)
    }
  }
}

When using the mapActions helper, the above code becomes the following:

import { mapActions } from 'vuex'

export default {
  methods: {
    ...mapActions({
      add: 'addTodo'
    }),
    addTodo(todo) {
      this.add(todo)
    }
  }
}

The mapActions helper returns an object, with each key-value pair being the name of the action (add in the example) and a string of the action's name in the store. The action can then be called from within the component like any other component method (e.g., this.add(todo)).

As we've seen with mapped getters, when using Vuex modules, all that's required is prepending the name of the module, followed by a /, to the name of the action. For example, if the addTodo action were located in a module named todos, the key-value pair would become the following:

add: 'todos/addTodo'

Rounding out the helpers: the mapMutations helper

The mapMutations helper, like the mapActions helper, maps mutations as component methods. Without mapMutations, we could have code that looks like this:

export default {
  methods: {
    markTodoComplete(todo) {
      this.$store.commit('MARK_COMPLETE', todo)
    }
  }
}

When using mapMutations, that code becomes the following:

import { mapMutations } from 'vuex'

export default {
  methods: {
    ...mapMutations({
      markComplete: 'MARK_COMPLETE'
    }),
    markTodoComplete(todo) {
      this.markComplete(todo)
    }
  }
}

As we've mentioned with some of the other helpers, when using Vuex modules, simply add the name of the module, followed by a /, to the beginning of the string. For example:

markComplete: 'todos/MARK_COMPLETE'

Final thoughts

There's certainly nothing wrong with using this.$store. If that approach seems easier to you, or it makes more sense to you, it's perfectly okay to continue accessing the Vuex store in that manner. But if you dislike typing that over and over again, or you find that it makes your code more difficult to read, then utilizing the Vuex map helpers is a good way to alleviate those pain points. It's worth noting that you can pick and choose which helpers to use; if you use one, you aren't locked into using the others.

You can find more information about Vuex in the official documentation. If you have any thoughts or questions, please share them with us @zaengle. We'd love to hear from you.

Want to read more tips and insights on working with a Vue development team that wants to help your organization grow for good? Sign up for our bimonthly newsletter.

By Rachel Opperman

Engineer

What happens when you cross years of study in biology and medicine with a degree in computer science? You get someone like Rachel.