Can someone explain when you would use a dispatch versus a commit?
I understand a commit triggers mutation, and a dispatch triggers an action.
However, isn't a dispatch also a type of action?
Dispatch triggers an action whereas commit triggers a mutation. $dispatch is always used from your methods in routes/components. It sends a message to Vuex store to perform some action. The action can be performed any time after the current tick so that it will not affect the frontend performance.
$dispatch sends a message to your vuex store to do some action. The action may be done anytime after the current tick, so that your frontend performance is not affected. You never commit from any of your components / routes. It is done only from within an action, and only when you have some data to commit.
It's possible for a store. dispatch to trigger multiple action handlers in different modules. In such a case the returned value will be a Promise that resolves when all triggered handlers have been resolved.
To use async and await with Vuex dispatch, we can add an action method that's an async function.
As you rightly said, $dispatch
triggers an action, and commit
triggers a mutation. Here is how you can use these concepts:
You always use $dispatch
from your methods in routes / components. $dispatch
sends a message to your vuex store to do some action. The action may be done anytime after the current tick, so that your frontend performance is not affected.
You never commit
from any of your components / routes. It is done only from within an action, and only when you have some data to commit. Reason: commit is synchronous and may freeze your frontend till it is done.
Let's consider this case: If you have to fetch some json data from server. In this case, you need to do this asynchronously so that your user interface is not unresponsive / frozen for a while. So, you simply $dispatch
an action and expect it to be done later. Your action takes up this task, loads data from server and updates your state later.
If you need to know when an action is finished, so that you can display an ajax spinner till then, you may return a Promise as explained below (example: load current user):
Here is how you define the "loadCurrentUser" action:
actions: { loadCurrentUser(context) { // Return a promise so that calling method may show an AJAX spinner gif till this is done return new Promise((resolve, reject) => { // Load data from server // Note: you cannot commit here, the data is not available yet this.$http.get("/api/current-user").then(response => { // The data is available now. Finally we can commit something context.commit("saveCurrentUser", response.body) // ref: vue-resource docs // Now resolve the promise resolve() }, response => { // error in loading data reject() }) }) }, // More actions }
In your mutations handler, you do all the commits originating from actions. Here is how you define the "saveCurrentUser" commit:
mutations: { saveCurrentUser(state, data) { Vue.set(state, "currentUser", data) }, // More commit-handlers (mutations) }
In your component, when it is created
or mounted
, you just call the action as shown below:
mounted: function() { // This component just got created. Lets fetch some data here using an action // TODO: show ajax spinner before dispatching this action this.$store.dispatch("loadCurrentUser").then(response => { console.log("Got some data, now lets show something in this component") // TODO: stop the ajax spinner, loading is done at this point. }, error => { console.error("Got nothing from server. Prompt user to check internet connection and try again") }) }
Returning a Promise as shown above is entirely optional and also a design decision not preferred by everyone. For a detailed discussion on whether to return a Promise or not, you may read the comments under this answer: https://stackoverflow.com/a/40167499/654825
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With