Vuex 4 — Modules
Tags: vue, webdev, programming, javascript
Published: 2021-01-26 01:21:22

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

### Modules

We can divide our Vuex 4 store into modules so that we can divide our states into multiple smaller parts.

Each module has their own state, mutations, actions, and getters.

### Module Local State

Each module has their own local state. We can map the module’s state into computed properties and mutations into methods by writing:

```
<!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>{{doubleCount}}</p>
    </div>
    <script>
      const moduleA = {
        state: () => ({
          count: 0
        }),
        mutations: {
          increment(state) {
            state.count++;
          }
        },
        getters: {
          doubleCount(state) {
            return state.count * 2;
          }
        }
      };

      const store = new Vuex.Store({
        modules: {
          moduleA
        }
      });
      const app = Vue.createApp({
        methods: {
          ...Vuex.mapMutations(["increment"])
        },
        computed: {
          ...Vuex.mapGetters(["doubleCount"])
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>
```

We created the store with the `modules` property to include our module in the store.

Then in our Vue instance, we have the `mapMutations` and `mapGetters` methods to map the mutations to methods and the getters to computed properties.

We can do the same with actions and states.

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>{{moduleA.count}}</p>
    </div>
    <script>
      const moduleA = {
        state: () => ({
          count: 0
        }),
        mutations: {
          increment(state) {
            state.count++;
          }
        },
        actions: {
          increment({ commit }) {
            commit("increment");
          }
        }
      };

      const store = new Vuex.Store({
        modules: {
          moduleA
        }
      });
      const app = Vue.createApp({
        methods: {
          ...Vuex.mapActions(["increment"])
        },
        computed: {
          ...Vuex.mapState({ moduleA: (state) => state.moduleA })
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>
```

We called the `mapActions` method with an array of action names.

The `mapState` method is called with an object with methods to return the module states.

The states are in the object with the module name as the property name.

### Namespacing

We can namespace our modules.

This way, we won’t have everything under one global namespace.

Also, this lets multiple modules react to the same mutation or action type.

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="this['moduleA/increment']">increment</button>
      <p>{{moduleA.count}}</p>
    </div>
    <script>
      const moduleA = {
        state: () => ({
          count: 0
        }),
        mutations: {
          increment(state) {
            state.count++;
          }
        },
        actions: {
          increment({ commit }) {
            commit("increment");
          }
        }
      };

      const store = new Vuex.Store({
        modules: {
          moduleA: {
            namespaced: true,
            ...moduleA
          }
        }
      });
      const app = Vue.createApp({
        methods: {
          ...Vuex.mapActions(["moduleA/increment"])
        },
        computed: {
          ...Vuex.mapState({ moduleA: (state) => state.moduleA })
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>
```

We mapped the action with the namespace name since we set the `namespaced` property to `true` .

We can do the same with getters and mutations.

To do that, we 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="this['moduleA/increment']">increment</button>
      <p>{{this['moduleA/doubleCount']}}</p>
    </div>
    <script>
      const moduleA = {
        state: () => ({
          count: 0
        }),
        mutations: {
          increment(state) {
            state.count++;
          }
        },
        getters: {
          doubleCount(state) {
            return state.count;
          }
        }
      };

      const store = new Vuex.Store({
        modules: {
          moduleA: {
            namespaced: true,
            ...moduleA
          }
        }
      });
      const app = Vue.createApp({
        methods: {
          ...Vuex.mapMutations(["moduleA/increment"])
        },
        computed: {
          ...Vuex.mapGetters(["moduleA/doubleCount"])
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>
```

We called `mapMutations` and `mapGetters` with the namespace name since we set `namespaced` to `true` in the module.

### Conclusion

We can create our modules and namespace them so that we can have multiple smaller parts of a store that manage their own state.