As Vuex documentation says, when the project start to grow we need a way to separate state management in a more self contained and modularized scalable solution. Here namespaces come in help. Sadly at the moment of writing Vuex modules section lacks of information and examples how to effectively use them.
This is my store structure
store
|- modules
|- core
|- country.js
|- region.js
|- ...
|- roullout
|- site.js
|- index.js
Here module register index.js
import Vuex from 'vuex'
// Core modules
import coreCountry from "@/store/modules/core/country";
import coreRegion from "@/store/modules/core/region";
// Rollout modules
import rolloutSite from "@/store/modules/rollout/site";
export default new Vuex.Store({
modules: {
// Core modules
core: {
country: coreCountry,
region: coreRegion,
},
// Rollout modules
rollout: {
site: rolloutSite
}
}
})
Now in some component I try to define actions
methods: {
...mapActions('rollout/site', [
LIST_REQUEST
])
}
Here the first error: rollout/site
is not found because I guess rollout
is a folder not a module and therefor site
is a module and not a nested module of rollout
.
Vuex documentation show how to use helper to bind stuff in nested modules but doesn't show the architecture of a store with nested modules.
LIST_REQUEST is an action, come from types.js and is defined as:
export const LIST_REQUEST = "rollout/site/LIST_REQUEST";
So in site.js module I can use as:
const actions = {
[types.LIST_REQUEST]: async ({ commit }, payload= {}) => {
// your actions here...
},
}
Since I'm using mapActions(), instead of dispatch actions like: this.$store.dispatch() I can directly do this.LIST_REQUEST()
import {
LIST_REQUEST
} from "@/store/types/rollout/site";
export default {
name: "SiteList",
created() {
this.LIST_REQUEST()
},
methods: {
...mapActions('rollout/site', [
LIST_REQUEST
])
}
}
Here another error: LIST_REQUEST() is not a function. This error come because mapAction still have to turn the action into function
How I can fix these problems with nested modules and use index.js. Maybe I have a bit of confusion in my mind, may you help to clarify these concepts?
I was completely misled by the question and the answer given in this post, and it probably also did so to numerous others as it had 1K views at the time of posting this. After figuring it out on my own, I decided to post it here so that it would not waste even more people's time.
Answer:
use
modules: {
core: {
namespaced: true,
modules {
// Core modules
country: coreCountry,
region: coreRegion,
}
},
rollout: {
namespaced: true,
modules: {
// Rollout modules
site: rolloutSite
}
}
}
(see the explanation below)
If you don't put in namespaced: true
within your coreCountry
, coreRegion
, and rolloutSite
, it will still be like this.$store.dispatch(rollout/LIST_REQUEST)
. Put in namespaced: true
in them if you want this.$store.dispatch(rollout/site/LIST_REQUEST)
or, like you said, this.LIST_REQUEST()
from using
methods: {
...mapActions('rollout/site', [
LIST_REQUEST
])
}
For the error with "LIST_REQUEST() is not a function" maybe it's fixed by now, but I thought "rollout/site/LIST_REQUEST" was a weird name for a function. Maybe you can make defining the action work using what you have (maybe by playing around with the syntax around it if it doesn't work?)
const actions = {
[types.LIST_REQUEST]: async ({ commit }, payload= {}) => {
// your actions here...
},
}
But, I would instead recommend the more common way (Vuex guide also uses this) to define the action:
actions: {
actionName (context, payload) {
// async functions and commits here
}
}
or
actions: {
actionName ({ state, rootState, commit, dispatch, getters, rootGetters }, payload) {
// async functions and commits here
}
}
Explanation:
whatever goes in the modules: { }
is considered a module, which by definition (defined in the Vuex API Reference) is an object that is
key: {
// required (can be empty)
state,
// optional (as denoted by '?')
namespaced?,
mutations?,
actions?,
getters?,
modules? // **nested modules go here**
}
So, there are no concept of folders within modules. When you put in
module {
core: { ... },
rollout: { ... }
}
core
and rollout
will be recognized as modules not folders.
So, having
module {
rollout: {
site: { ... }
}
}
makes no sense whatsoever. whatever goes inside rollout
(recognized as a module) should be either state:
, namespaced:
, mutations:
, actions:
, getters:
, or modules:
. Nothing else.
So, to put in a module inside modules: { }
you can either
modules: { coreCountry, coreRegion }
modules: { country: coreCountry, region: coreRegion }
core: { module content here }
and rollout: { module content here }
in the answer I gave, or the account
in vuex guideBasically, to make nested modules, you just had to put in the sub-modules within the modules: { }
of the parent modules (can either be defined on the spot like the answer or be made somewhere else and imported) like core
and rollout
which are in the modules: { }
of the root store themselves.