Getting Started with Vuex 4 with Vue 3

John Au-Yeung - Jan 26 '21 - - Dev Community

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.

Installation

We can install it from CDN.

To do that, we add the script tag for Vuex.

Then we can use that to create the app 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>{{count}}</p>
    </div>
    <script>
      const store = new Vuex.Store({
        state: {
          count: 0
        },
        mutations: {
          increment(state) {
            state.count++;
          }
        }
      });

      const app = Vue.createApp({
        methods: {
          increment() {
            this.$store.commit("increment");
          }
        },
        computed: {
          count() {
            return this.$store.state.count;
          }
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

We included the global version of Vuex so that we can use it with HTML script tags.

In the code above, we created a store with the Vuex.Store constructor.

The state has the store’s states.

We have the count state with the count.

mutations has the store mutations.

It has the inctrement mutation method to increment the count state.

Then in our root Vue instance, we have the increment method that calls the this.$store.commit method to increment the count state.

And we have the computed count property to return the count state from the store.

The store state is accessible with the this.$store.state property.

We call the increment method when we click on the increment button.

Then we see the count state updated and displayed in the template via the computed property.

We have th remember to add:

app.use(store);
Enter fullscreen mode Exit fullscreen mode

so that the store can be used with our Vue 3 app.

The changes are reactive, so whenever the store’s state changes, we’ll get the latest changes in our components.

Getters

We can add getters to make getting states easier.

Instead of computed properties, we can use getters to get the latest value of our state.

To add a getter, 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">
      <div>
        <p v-for="d of doneTodos" :key="d.id">{{d.text}}</p>
      </div>
    </div>
    <script>
      const store = new Vuex.Store({
        state: {
          todos: [
            { id: 1, text: "eat", done: true },
            { id: 2, text: "sleep", done: false }
          ]
        },
        getters: {
          doneTodos: (state) => {
            return state.todos.filter((todo) => todo.done);
          }
        }
      });

      const app = Vue.createApp({
        computed: {
          ...Vuex.mapGetters(["doneTodos"])
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

to create a doneTodos getter in our store and use it in our Vue instance with the Vuex.mapGetters method.

The argument is an array of strings with the name of the getters.

We spread the computed properties into the computed object so that we can access the in our component.

In the template, we render the items from the getter.

The doneTodos method has the state parameter with the state.

It can also receive other getters as a second argument.

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">
      <div>
        <p v-for="d of doneTodos" :key="d.id">{{d.text}}</p>
        <p>{{doneTodosCount}} done</p>
      </div>
    </div>
    <script>
      const store = new Vuex.Store({
        state: {
          todos: [
            { id: 1, text: "eat", done: true },
            { id: 2, text: "sleep", done: false }
          ]
        },
        getters: {
          doneTodos: (state) => {
            return state.todos.filter((todo) => todo.done);
          },
          doneTodosCount: (state, getters) => {
            return getters.doneTodos.length;
          }
        }
      });

      const app = Vue.createApp({
        computed: {
          ...Vuex.mapGetters(["doneTodos", "doneTodosCount"])
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

We have the doneTodosCount getter with the getters object that has our getters.

We used it to access the doneTodos getter with it and used mapGetters to display to make it accessible in our component.

Then we should see the todos that have done set to true and get 1 done in our component displayed.

Conclusion

We can create a simple Vue 3 app with Vuex 4 with a simple store and getters.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .