Accessing getters or actions from another Vuex module

Ste Griffiths - Aug 7 '23 - - Dev Community

This is a cheatsheet. Say you have multiple named modules in your Vuex store and you need to access something from more than one of them at a time, or they need to talk to each other. How do we do that?

For these demos, imagine a store with modules called trees, seasons, and weather:

import trees from "./modules/trees";
import seasons from "./modules/seasons";
import weather from "./modules/weather";

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    trees,
    seasons,
    weather,
  },
});

Enter fullscreen mode Exit fullscreen mode

Any getter from a component

The easy part. You can mapGetters from one or more different modules in the computed section of a component:

import { mapGetters } from "vuex";

export default {
  name: "MyComponent",
  ...
  computed: {
    ...mapGetters("trees", ["isEvergreen"]),
    ...mapGetters("seasons", [
      "isTropicalSeason",
      "isRainySeason",
    ]),
    ...
  }

Enter fullscreen mode Exit fullscreen mode

Here we map the trees.isEvergreen, seasons.isTropicalSeason, and seasons.isRainySeason getters.

The first param to mapGetters is module name, the second is an array of getter names, all as strings.

Any getter from an action

The first param of every action is the whole store, and it is normal to destructure this using braces to access the members you need, which can include getters (for same module) and rootGetters (for accessing any module):

// An action:
async tryTreeGrowth({ commit, rootGetters }, sapling) {
  const growingConditions = await getGrowingConditions(
    rootGetters["weather/getWeeklyWeather"],
    rootGetters["seasons/getSeason"],
    sapling
  );
  if (growingConditions > 0.5)
    commit("DO_GROWTH", sapling);
},

Enter fullscreen mode Exit fullscreen mode

Any getter from another getter

If you’re doing this, it’s probably a mistake. You should probably abstract this “one level up” in your component or action; grabbing the various values you need from each module and combining them there.

However, there is a way. On a getter, there are four fixed parameters (they don’t use destructuring like actions do): (state, getters, rootState, rootGetters). If you don’t need to use one or more of them, you can “throw them away” by using a variable name that’s a number of underscores. This will stop eslint/prettier complaining about unused variables.

// Getter in the weather module:
isWeatherSeasonal(_, getters, __, rootGetters) {
  return (getters.isRainy && rootGetters["seasons/isRainySeason"])
    || (getters.isDry && rootGetters["seasons/isDrySeason"])
}

Enter fullscreen mode Exit fullscreen mode

We have _ in place of state, and __ in place of rootState, because neither of those is used in the function.

Any action from another action

When you destructure the store as a parameter of an action, you can grab the dispatch method. Dispatch allows you to call any action from any module, using a name with a slash, as long as you pass a third parameter (options) with { root: true }:

// Action in the weather module:
resetClimate({ dispatch }) {
  // Also reset climate in the 'seasons' module
  dispatch("seasons/resetClimate", null, { root: true });
},

Enter fullscreen mode Exit fullscreen mode

In the example code above, the action takes no input, it’s just a “do this”.

Alright, have fun out there 🦥🍒

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