Vuex 4 — Actions
Tags: vue, webdev, programming, javascript
Published: 2021-01-26 01:20:32

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


**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.