The mapState alias supports one-level only.
Can we support the child state with the alias like this:
computed: mapState
({
screen: 'homepage.screen'
})
Instead of doing this?
computed: mapState
({
screen: state => state.homepage.screen
})
How about passing array of string instead of dot-separated keys?
mapState({
screen: ['homepage', 'screen']
})
Because some keys can be looks weird like array.key.0. or some.hyphen-key.
Also, if a key includes dot character, we cannot get its value by the string alias.
+1 although I'd like to access state using a dot delimited string like
computed: mapState
({
screen: 'homepage.screen'
})
Yeah I actually tried 'homepage.screen', foolishing assuming it would work. +1 seems like a good idea.
+1 for the dot delimited string
Given that you can do
...mapActions('some/nested/module', [
'foo',
'bar'
])
...it would only make sense to me to make it so you can do
...mapState('some/nested/module', [
'abc',
'def'
])
I actually thought this was a bug at first, until I realized it's just really inconsistent.
+1 although I'd like to access state using a dot in the string array like
computed: mapState(['logged', 'modalLogin', 'homePage.inHomePage'])
instead of:
computed: {
inHomePage () {
return this.$store.state.homePage.inHomePage
},
...mapState(['logged', 'modalLogin'])
}
...mapState({
loading: ['userManage','loading'],
tableData: ['userManage','tableData'],
rowCount: ['userManage','rowCount'],
showGoBack: ['userManage','showGoBack'],
showPager:['userManage','showPager']
})
I tried like this,but it didn`t work
How about passing array of string (alias) instead as third argument?
export default {
computed: {
...mapGetters('sidebar', ['isOpen'], ['isSidebarOpen'])
}
}
As @zysallen point out, it seem doesn't work. but it work like this: screen: state => state.homepage.screen.
So let me get this straight, everything is available globally but the state, right? (With namespacing turned off)
So I can get an action by doing:
...mapActions(['moduleAction'])
But if I want to get a modules state I have to either do this in computed:
moduleState() {
return this.$store.state.module.moduleState
}
Or:
...mapState({ moduleState: state => state.module.moduleState })
So that's what it looks like when state is namespaced by default.
And then if I turn namespacing to true, I can get actions in a module like this:
...mapActions('module', [
'moduleAction'
])
Which is a completely different syntax than the state, but both are namespaced?
Why is it like this? Why can't I just get the state the same way I'm getting the actions if you insist on it being namespaced by default? Why not have at least consistent syntax?
Something like:
...mapState('module', [
'moduleState'
])
Just like I get the actions, getters and mutations if I choose to namespace them?
with vuex modules
when namespaced is false
why i can't use like this?
...mapState('module', ['a'])
instead of
...mapState({a: state => state.module.a})
state in modules is namespaced already right? It make no sense..
Because a namespace and a module path can be different. Imagine the following case:
const store = new Vuex.Store({
modules: {
parent: {
modules: {
foo: {
namespaced: true,
state: {
value: 123
},
mutations: {
inc (state) {
state.value += 1
}
}
}
}
}
}
})
// `parent.foo` module is namespaced by `foo`
mapState('foo', ['value'])
mapMutations('foo', ['inc'])
Could anyone with a good knowledge of Vuex provide a mapStateFromModule(modulePath, Array<string> | Object) utility function that we could use to avoid the current verbose syntax, when namespaced is false? Would be much appreciated, thanks!
Ok, I went ahead and tried a basic implementation:
function appendModuleName(moduleName, array){
let res = {};
array.forEach(function(moduleState){
res[moduleState] = function(state){
return state[moduleName][moduleState];
};
});
return res;
}
You use it like:
computed: mapState(appendModuleName('moduleName', ['moduleState1','moduleState2']))
Obviously a pretty limited solution, but just to give an idea of what I'm looking for.
This definitely seems like a must have for Vuex. I would much prefer the dot notation string over array syntax which is almost as vebose as the fat arrow function version.
I would love to be able to write mapState([ 'module.moduleState']) and get either a computed moduleState or a computed object module: { moduleState: ... }.
It just seems natural and theoretically shouldn't break the current interface unless people are using dots in their property names for some reason.
:+1:
I have also just instinctively tried to use the dot notation to map state from a module. Ended up here after searching for how to do it.
This is a huge gotcha and very counterintuitive. For some reason having the state not namespaced = it's not available to you? MapState should act like the other map functions. Very frustrating and confusing.
馃憤
:+1:
Also attempted several variations of this, also instinctively started with dot notation. Would love to see this implemented.
I don't know if this helps because I don't know the vuex codebase, but a function to get a deep value from an object is simple like this:
function deepValue(obj, key) {
return key.split('.').reduce((child, key) => {
if (child && key in child)
return child[key]
return undefined
}, obj)
}
I use it here https://github.com/oswaldofreitas/vulma/blob/master/utils/object.js#L1-L7
Similar functionality can be achieved with createNamespacedHelpers. Although I prefer the dot notation to avoid creating methods for every module
https://vuex.vuejs.org/en/modules.html#binding-helpers-with-namespace
Hey guys. How about this approach?
computed: {
...[
"data1",
"data2",
"data3",
"data4"
].reduce((prev, cur) => {
prev[cur] = function() {
return this.$store.state.your.nested.state[cur];
};
return prev;
}, {}),
}
Many guys mentioned modules but I ended up here for spreading nested child state without modules and maybe some guys are same as me.
Hope my approach helpful to you.
I did so
computed: {
...mapState({
name: state => state.module.name
})
}
There are other better ideas?
For a namespaced state, we can still use this:
...mapState('admin', {
form: state => state.form.userDetails,
}),
Namespaced state should be accesed like mapActions
methods: {
...mapActions({
doSearch: 'search/doSearch'
})
}
computed: {
...mapState({
results: 'search/results'
})
}
I quickly rigged the following (in TypeScript) to sloppily solve this problem:
import {mapState} from 'vuex';
function mapModuleState(moduleName: string, keys: string[]) {
const parts = moduleName.split('.');
const enterPath = (obj: any, parts: string[]): any => {
parts.forEach(part => (obj = obj[part]));
return obj;
};
const result: {[key: string]: any} = {};
keys.forEach(k => {
result[k] = (state: any) => enterPath(state, parts)[k];
});
return mapState(result);
}
And then in your component, you would run something like the following:
computed: {
...mapModuleState("moduleName", ["a", "b"]),
(note: I haven't rigorously tested this)
Here's a JS version
function mapModuleState(moduleName, keys) {
const parts = moduleName.split('.');
const enterPath = (obj, parts) => {
parts.forEach(part => obj = obj[part]);
return obj;
};
const result = {};
keys.forEach(k => {
result[k] = state => enterPath(state, parts)[k];
});
return mapState(result);
}
This issue was opened in 2016, is there any progress or attempt being made to move this forward? As others have explained, it's extremely counter-intuitive to not allow dot-notation for non-namespaced modules.
Expanding on that point, the fact that there is different syntax for mapState, mapGetters, and mapActions is extremely confusing and not intuitive at all. The syntax should be the same, or as close to being the same as is possible. I personally don't see a reason why the syntax can't be identical for all helper methods; their base data are essentially all objects.
I think it's acceptable since the dot-notation is more like a workaround instead of an answer that truly solved the problem.
Also, they are planning to remove the verbose mapXXX helpers in Vuex 4.x.
Vuex 4.x
- Simplify usage
- Getting rid of
mapXXXhelpers via scoped-slot based store consumer component
- Getting rid of the need for separating actions and mutations
This tool maps getters and setters using dot notation: https://github.com/maoberlehner/vuex-map-fields
Closing the issue due to its age. Though another problem is that dot notation is not possible type 馃 Also, we have module system now, and it might be confusing whether it's trying to fetch nested state, or nested module state (kinda same thing though).
Most helpful comment
Given that you can do
...it would only make sense to me to make it so you can do
I actually thought this was a bug at first, until I realized it's just really inconsistent.