actions
Vuex offers a great way to mutate state items with the use of mutations and actions. Vuex-asr enables you to bind those actions and mutations the same way you could bind state and getters by the component's attributes. In this chapter we discuss the use of actions.
codesandbox
vuex actions in a nutshell
Actions are methods in the store used for asynchronous interaction of data, typically triggered by an event, like fetching data from an API and commit
the received data as a mutation to mutate the state. You could make multiple commits in an action and you have access to all of the state and mutations in the store (and it's namespaces).
TIP
Keeping track of mutations (e.g. triggered by actions) is very handy for debugging. It's recommended to download the vue.js devtools for chrome. If you go to the Vuex
tab in it you'll see your mutations and state.
You could read more about actions in the vuex guide/actions.
when to use a mutation or an action
This convention could help you to decide to use mutations or actions:
- if you are updating a single state item, you could use a mutation, but more elegantly it would be to create an action that commits a mutation.
- If you have to update multiple state items or have an asynchronous procedure in one method you should always use an action.
the store
Let's take a look at the following store,
// src/vuex/store.js
export default new Vuex.Store({
state: {
message: "message in the root of the store",
},
mutations: {
setMessage(state, message) {
console.log("message was mutated with: ", message);
state.message = message;
}
},
actions: {
setMessageAsync({ commit }, event) {
setTimeout(() => {
// NOTE: one or more commits possible
commit("setMessage", event.target.value);
}, 1000);
}
}
});
We have an action setMessageAsync
that delays 1 sec (to simulate async behaviour) before committing the mutation setMessage
.
creating a two way binding with a state item and an action
We bind a state item and an action to a component
// src/App.vue
<template>
<example-component-with-event-handler
asr-bind-state="message"
asr-bind-action="setMessageAsync AS setMessage"
/>
</template>
...
The component now has state item message
and method setMessage
available:
(note that the component below is still the same component we used in the mutations example)
// src/components/ExampleMessageWithEventHandler.vue
<template>
<p class="message">{{ message }}</p>
<input v-bind:value="message" @keyup="setMessage">
</div>
</template>
Notice we bind the message
to the value attribute of of the input
element and an event-handler setMessage
that get's triggered at the keyup event.
And voila we have a nice two way binding at our hands implementing an action.
aliasing
Since we are also able to alias our actions we could easily reuse this component to create an instance with other store bindings:
Let's say we have:
export default new Vuex.Store({
state: {
anotherMessage: "another message in the root of the store"
},
mutations: {
setAnotherMessage(state, message) {
console.log("anotherMessage was mutated with: ", message);
state.anotherMessage = message;
}
},
actions: {
setAnotherMessageAsync({ commit }, event) {
setTimeout(() => {
commit("setAnotherMessage", event.target.value);
}, 1000);
}
});
now we could bind the component like this (and reuse it):
// src/App.vue
<template>
<example-component-with-event-handler
asr-bind-state="anotherMessage AS message"
asr-bind-actions="setAnotherMessageAsync AS setMessage"
/>.
</template>
...
namespacing
As namespacing is a generic feature of vuex-asr could work like this:
// src/App.vue
<template>
<example-component-with-event-handler
asr-bind-state="GENERAL/anotherMessage AS message"
asr-bind-actions="GENERAL/setAnotherMessageAsync AS setMessage"
/>
</template>
...
next steps
In the next chapters we go deeper into aliasing and namespacing and how these features could help us to improve the organisation of our front-end codebase.