Vuex 2.0 Dispatch versus Commit

Javascriptvue.jsVuex

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionimchingyView Question on Stackoverflow
Solution 1 - JavascriptManiView Answer on Stackoverflow