Vuex 4 is in beta and it’s subject to change.
Vuex is a popular state management library for Vue.
Vuex 4 is the version that’s made to work with Vue 3.
In this article, we’ll look at how to use Vuex 4 with Vue 3.
Actions
In Vuex 4, actions are similar to mutations.
The differences are that actions commit mutations and actions can have async operations.
To create an action, we can add an actions
property to our store.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vuex@4.0.0-beta.4/dist/vuex.global.js"></script>
<title>App</title>
</head>
<body>
<div id="app">
<button @click="increment">increment</button>
<p>{{count}}</p>
</div>
<script>
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
increment(context) {
context.commit("increment");
}
}
});
const app = Vue.createApp({
methods: {
increment() {
this.$store.dispatch("increment");
}
},
computed: {
count() {
return this.$store.state.count;
}
}
});
app.use(store);
app.mount("#app");
</script>
</body>
</html>
We created a Vuex store with an actions
property that has the increment
method in it.
It takes the comtext
parameter with the commit
method to commit mutations.
To dispatch the action in our component, we call this.$store.dispatch
with the action name.
We can perform async operations in an action.
For example, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vuex@4.0.0-beta.4/dist/vuex.global.js"></script>
<title>App</title>
</head>
<body>
<div id="app">
<button @click="increment">increment</button>
<p>{{count}}</p>
</div>
<script>
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementAsync({ commit }) {
setTimeout(() => {
commit("increment");
}, 1000);
}
}
});
const app = Vue.createApp({
methods: {
increment() {
this.$store.dispatch("incrementAsync");
}
},
computed: {
count() {
return this.$store.state.count;
}
}
});
app.use(store);
app.mount("#app");
</script>
</body>
</html>
We called commit
inside the setTimeout
callback to delay the action dispatch by a second.
Also, we can dispatch actions with a payload.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vuex@4.0.0-beta.4/dist/vuex.global.js"></script>
<title>App</title>
</head>
<body>
<div id="app">
<button @click="increment">increment</button>
<p>{{count}}</p>
</div>
<script>
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state, payload) {
state.count += payload.amount;
}
},
actions: {
incrementAsync({ commit }, payload) {
setTimeout(() => {
commit("increment", payload);
}, 1000);
}
}
});
const app = Vue.createApp({
methods: {
increment() {
this.$store.dispatch("incrementAsync", { amount: 2 });
}
},
computed: {
count() {
return this.$store.state.count;
}
}
});
app.use(store);
app.mount("#app");
</script>
</body>
</html>
We added a payload
parameter to the incrementAsync
action to accept payloads in our action.
Then we pass in an object as the 2nd argument to the this.$store.dispatch
method to dispatch our action.
We can also pass in an object with the type
property and arbitrary properties that will be included in the payload:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vuex@4.0.0-beta.4/dist/vuex.global.js"></script>
<title>App</title>
</head>
<body>
<div id="app">
<button @click="increment">increment</button>
<p>{{count}}</p>
</div>
<script>
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state, payload) {
state.count += payload.amount;
}
},
actions: {
incrementAsync({ commit }, payload) {
setTimeout(() => {
commit("increment", payload);
}, 1000);
}
}
});
const app = Vue.createApp({
methods: {
increment() {
this.$store.dispatch({ type: "incrementAsync", amount: 2 });
}
},
computed: {
count() {
return this.$store.state.count;
}
}
});
app.use(store);
app.mount("#app");
</script>
</body>
</html>
The type
is the name of the action and the other properties will end up in the payload
object in the 2nd argument of the incrementAsync
action.
Conclusion
We can create actions to commit mutations and run async code with Vuex 4.