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,
},
});
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",
]),
...
}
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);
},
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"])
}
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 });
},
In the example code above, the action takes no input, it’s just a “do this”.
Alright, have fun out there 🦥🍒