Using Vuex with the Vue Composition API
While I was learning the Vue Composition API, something suddenly hit me. What about Vuex? How will I beautifully map my getters, mutations and actions like I currently do with the Options API?
Well, here are two ways to use Vuex with the new Vue Composition API.
Prefer screencasts? You'll find this and more over on the Vue Composition API course!
The store
To keep things simple, let's use a store that exists just to increment a number (pointless in reality).
export default new Vuex.Store({ state: { counter: 0 }, getters: { counter (state) { return state.counter } }, mutations: { SET_COUNTER (state, value) { state.counter = value } }, actions: { incrementCounter ({ commit, state }, increment) { commit('SET_COUNTER', state.counter + increment) } }})
No modules here, but the two methods we're going to look at both work with namespaced modules.
With our store defined, let's look at the two methods we can use to get Vuex hooked up in our components.
1. Access the store directly
This isn't everyone's cup of tea, but it works well for smaller components that don't use too many getters, mutations or actions.
import { computed } from '@vue/composition-api' export default { setup (props, { root }) { const counter = computed(() => root.$store.getters.counter) function incrementCounter (increment) { root.$store.dispatch('incrementCounter', increment) } return { counter, incrementCounter } }}
What's happening here:
- We've destructured the context passed through as the second argument to
setup
, giving us access to theroot
Vue instance - The computed property
counter
gives us a reactive value for the currentcounter
getter value - The
incrementCounter
function dispatches an action
This way, we can make use of the counter
value and incrementCounter
function in our component template.
<template> <div> {{ counter }} <a href="#" @click.prevent="incrementCounter(1)">Increment</a> </div></template>
2. Use the vuex-composition-helpers package
This'll feel more natural if you're used to working with mapGetters
and mapActions
in your components with the Options API.
The first thing you'll need to do is install the package.
Then, it's as simple as mapping getters, mutations, actions or state much like you're used to, using the functions provided.
import { useGetters, useActions } from 'vuex-composition-helpers'; export default { setup (props) { const { counter } = useGetters({ counter: 'counter' }) const { incrementCounter } = useActions({ incrementCounter: 'incrementCounter' }) return { counter, incrementCounter } }}
The result in our template is exactly the same.
<template> <div> {{ counter }} <a href="#" @click.prevent="incrementCounter(1)">Increment</a> </div></template>
Out of habit, I'm passing objects through to the useGetters
and useActions
functions, but you can pass an array of items, too.
const { incrementCounter } = useActions(['incrementCounter'])
Once again, this will work with namespaced modules. As an example, if you had an auth module which contained authenticated
and user
getters, you'd do this.
const { authenticated, user } = useGetters({ authenticated: 'auth/authenticated', user: 'auth/user',})
Beautiful.
That's all
Nice. You have two solutions for using Vuex with the Composition API.
At the time of writing, Vue 3 hasn't officially been released, and Vuex may add support for this natively. I can't promise there won't be better solutions by the time you read this, but I doubt much will change.