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!
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.
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:
setup
, giving us access to the root
Vue instancecounter
gives us a reactive value for the current counter
getter valueincrementCounter
function dispatches an actionThis 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>
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.
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.