Categories
Vue

Adding Getters to a Vuex Store

Spread the love

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

With Vuex, we can store our Vue app’s state in a central location.

In this article, we’ll look at how to add getters to a Vuex store to add states derived from other store states.

Adding Getters to Our Store

We can add a getter to our Vuex store by adding a getters property as follows:

index.js :

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: "todo1", done: true },
      { id: 2, text: "todo2", done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done);
    }
  }
});

new Vue({
  el: "#app",
  store,
  computed: {
    doneTodos() {
      return this.$store.getters.doneTodos;
    },
    ...Vuex.mapState({
      todos: "todos"
    })
  }
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vuex"></script>
  </head>
  <body>
    <div id="app">
      <div>
        <p>Todos:</p>
        <div v-for="todo of todos">{{todo.text}}</div>
        <p>Done Todos:</p>
        <div v-for="todo of doneTodos">{{todo.text}}</div>
      </div>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In the code, we have a getters object:

getters: {
  doneTodos: state => {
    return state.todos.filter(todo => todo.done);
  }
}

that derives the state from the todos state.

Then we accessed doneTodos getter by writing:

computed: {
  doneTodos() {
    return this.$store.getters.doneTodos;
  },
  ...Vuex.mapState({
    todos: "todos"
  })
}

in the Vue instance.

Then the items are rendered in our template and we get:

Todos:

todo1
todo2
Done Todos:

todo1

displayed.

Method-Style Access

We can return a function in a getter function so that we can call the getters from a component with one or more arguments.

For instance, if we want to make a getter that gets a todo by ID, we can write the following:

index.js :

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: "todo1", done: true },
      { id: 2, text: "todo2", done: false }
    ]
  },
  getters: {
    getTodoById: state => id => {
      return state.todos.find(todo => todo.id === id);
    }
  }
});

new Vue({
  el: "#app",
  store,
  computed: Vuex.mapState({
    todos: "todos"
  }),
  methods: {
    getTodoById(id) {
      return this.$store.getters.getTodoById(id);
    }
  }
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vuex"></script>
  </head>
  <body>
    <div id="app">
      {{getTodoById(1).text}}
    </div>
    <script src="index.js"></script>
  </body>
</html>

Then we see todo1 displayed on the screen.

We have the following code to define our getter:

getters: {
  getTodoById: state => id => {
    return state.todos.find(todo => todo.id === id);
  }
}

The code above returns a function and then returns a todo with the given ID.

Then we access it in our Vue instance by defining the getTodoById method as follows:

getTodoById(id) {
  return this.$store.getters.getTodoById(id);
}

Finally, we render it in our template by writing:

{{getTodoById(1).text}}

The mapGetters Helper

We can use the mapGetters helper to map our getters to computed properties as follows:

index.js :

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: "todo1", done: true },
      { id: 2, text: "todo2", done: false }
    ]
  },
  getters: {
    doneTodosCount: state => {
      return state.todos.filter(todo => todo.done).length;
    }
  }
});

new Vue({
  el: "#app",
  store,
  computed: Vuex.mapGetters(["doneTodosCount"])
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vuex"></script>
  </head>
  <body>
    <div id="app">
      {{doneTodosCount}}
    </div>
    <script src="index.js"></script>
  </body>
</html>

Then we get 1 displayed since we mapped doneTodosCount getter to a computed property with the same name with:

computed: Vuex.mapGetters(["doneTodosCount"])

Conclusion

We can use getters to add states that are derived from another state.

To define a getter, we add a method to the getters property that returns something derived from the state or a function that derives something from a state.

To include it in our components, we can use the this.$store.getters method or use the mapGetters method.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *