Getters

Getters are exactly the equivalent of computed values for the state of a Store. They can be defined with the getters property in defineStore(). They receive the state as the first parameter to encourage the usage of arrow function:

export const useStore = defineStore("main", {
  state: () => ({
    counter: 0
  }),
  getters: {
    doubleCount: (state) => state.counter * 2
  }
})

Most of the time, getters will only rely on the state, however, they might need to use other getters. Because of this, we can get access to the whole store instance through this when defining a regular function but it is necessary to define the type of the return type (in TypeScript). This is due to a known limitation in TypeScript and doesn't affect getters defined with an arrow function nor getters not using this:

export const useStore = defineStore("main", {
  state: () => ({
    counter: 0
  }),
  getters: {
    // automatically infers the return type as a number
    doubleCount(state) {
      return state.counter * 2
    },
    // the return type **must** be explicitly set
    doublePlusOne(): number {
      // autocompletion and typings for the whole store ✨
      return this.doubleCount + 1
    }
  }
})

Then you can access the getter directly on the store instance:

export default function () {
  const [store] = useStore()

  return <p>Double count is {store.doubleCount}</p>
}

Accessing other getters

As with computed properties, you can combine multiple getters. Access any other getter via this. Even if you are not using TypeScript, you can hint your IDE for types with the JSDoc:

export const useStore = defineStore("main", {
  state: () => ({
    counter: 0
  }),
  getters: {
    // type is automatically inferred because we are not using `this`
    doubleCount: (state) => state.counter * 2,
    // here we need to add the type ourselves (using JSDoc in JS). We can also
    // use this to document the getter
    /**
     * Returns the counter value times two plus one.
     *
     * @returns {number}
     */
    doubleCountPlusOne() {
      // autocompletion ✨
      return this.doubleCount + 1
    }
  }
})

Passing arguments to getters

Getters are just computed properties behind the scenes, so it's not possible to pass any parameters to them. However, you can return a function from the getter to accept any arguments:

export const useStore = defineStore("main", {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    }
  }
})

and use in component:

export default function () {
  const [store] = useStore()

  const { getUserById } = store

  return <p>User 2: {getUserById(2)}</p>
}

Note that when doing this, getters are not cached anymore, they are simply functions that you invoke. You can however cache some results inside of the getter itself, which is uncommon but should prove more performant:

export const useStore = defineStore("main", {
  getters: {
    getActiveUserById(state) {
      const activeUsers = state.users.filter((user) => user.active)
      return (userId) => activeUsers.find((user) => user.id === userId)
    }
  }
})

Accessing other stores getters

To use another store getters, you can directly use it inside of the getter:

import { useOtherStore } from "./other-store"

export const useStore = defineStore("main", {
  state: () => ({
    // ...
  }),
  getters: {
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.localData + otherStore.data
    }
  }
})

Usage with component

You can directly access any getter as a property of the store (exactly like state properties):

export default function () {
  const [store] = useStore()

  store.counter = 3
  store.doubleCount // 6

  return <p>Double count is {store.doubleCount}</p>
}