アリ・ナディム
アリ・ナディム

Reputation: 610

What is the special use of getters in vuex?

It's been two weeks studying vuex. I just wonder what is really the special function or use of the getters

I tried the code below and it's working fine.

this.$store.getters["app/url"]

But in the same way, I can get the same value by using the state

this.$store.state.app.url

I just ask because getters needs setup like below, and it lengthens the code when we could just get the value by using state.

const getters = {
    url: state => state.url 
};

Upvotes: 1

Views: 2420

Answers (2)

Owl
Owl

Reputation: 6853

getters is used when you want to apply logic when getting some data from state, Vuex doc explains it best

You can think of them as computed properties for stores.

For example you have array of items on your state:

items = [
    {
        name: "Keyboard",
        price: 100
    },
    {
        name: "Mouse",
        price: 50
    },
    {
        name: "Monitor",
        price: 500
    },
    {
        name: "PC",
        price: 1500
    },
    {
        name: "Headset",
        price: 80
    }
]

and you want to get list of items from state that cost more than 250, you can do

getExpensiveItems(state) {
    return state.items.filter(i => i.price > 250);
}

Read more about Vuex getters here

Sometimes we may need to compute derived state based on store state, for example filtering through a list of items and counting them:

computed: {
 doneTodosCount () {
   return this.$store.state.todos.filter(todo => todo.done).length
 }
}

If more than one component needs to make use of this, we have to either duplicate the function, or extract it into a shared helper and import it in multiple places - both are less than ideal.

Vuex allows us to define "getters" in the store. You can think of them as computed properties for stores. Like computed properties, a getter's result is cached based on its dependencies, and will only re-evaluate when some of its dependencies have changed.

Upvotes: 2

Sumurai8
Sumurai8

Reputation: 20745

I think there are three situations where getters have some advantage over just using the state:

  • First and foremost, getters can return internal data in a better format than the format it is stored in in the internal state. By moving this kind of processing to your Vuex store, you can keep your component clean. For example, you can have something like this:
// Normally we probably use setters here, but this is an example...
const state = {
  values: {
    2014: 1000,
    2015: 2000,
    2016: 3000,
    2017: 4000,
    2018: 5000,
    2019: 6000,
    2020: 7000
  },
  startYear: 2016,
  endYear: 2019
}

const getters = {
  // Returns something like [3000, 4000, 5000, 6000]
  currentValues (state) {
    const years = Object.keys(state.values);
    years.sort();

    return years
      .filter(year => year >= state.startYear && year <= state.endYear)
      .map(year => state.values[year]);
  }
}
  • You make it a lot easier to return copies of data, rather than the data itself, preventing you from accidentally modifying the store without the use of mutations. With the use of a lodash deepClone or Object.assign for shallow objects you can create copies that you can freely modify in your component without doing anything in the store.
const state = {
  values: {
    2014: 1000,
    2015: 2000,
    2016: 3000,
    2017: 4000,
    2018: 5000,
    2019: 6000,
    2020: 7000
  },
}

// In your component
const values = this.$store.state.values;
values[2021] = 8000;
// Wait, why is my store suddenly modified?!
// Instead, use a getter

import { cloneDeep } from 'lodash-es';

const getters = {
  values (state) {
    return cloneDeep(state.values);
  }
}

// In your component you can add 2021 without modifying the state and causing all kind of unintended/hard-to-debug side effects
  • Getters allow you to decouple the internal state of your Vuex store from components that use it. It basically creates a contract between the component and the Vuex store that allows you to modify the internal structure of your Vuex store or modify your component, without having to touch both the store and the component at once. This might help making it manageable to refactor some of your code. While there is some boilerplate in setting up initial getters, you can also just create a helper function that generates those getters for you. If for some reason you need to make a getter more complicated than returning the state, you can simply remove it from an automatically generated getter and write your own implementation. Otherwise you have to track down everywhere where the internal state was used.
function generateGetters(keys) {
  return keys.reduce((acc, key) => {
    acc[key] = (state) => state[key];

    return acc;
  }, {});
}

const getters = {
  ...generateGetters(['values', 'url', 'someOtherKey'])
}

Upvotes: 4

Related Questions