Adding Getters to a Vuex Store

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/

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"  
    })  
  }  
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

In the code, we have a getters object:

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

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"  
  })  
}
Enter fullscreen mode Exit fullscreen mode

in the Vue instance.

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

Todos:todo1  
todo2  
Done Todos:todo1
Enter fullscreen mode Exit fullscreen mode

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);  
    }  
  }  
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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);  
  }  
}
Enter fullscreen mode Exit fullscreen mode

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);  
}
Enter fullscreen mode Exit fullscreen mode

Finally, we render it in our template by writing:

{{getTodoById(1).text}}
Enter fullscreen mode Exit fullscreen mode

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"])  
});
Enter fullscreen mode Exit fullscreen mode

index.html :

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

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

computed: Vuex.mapGetters(["doneTodosCount"])
Enter fullscreen mode Exit fullscreen mode

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.

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