Please consider the example below
// Example state
let exampleState = {
counter: 0;
modules: {
authentication: Object,
geotools: Object
};
};
class MyAppComponent {
counter: Observable<number>;
constructor(private store: Store<AppState>){
this.counter = store.select('counter');
}
}
Here in the MyAppComponent
we react on changes that occur to the counter
property of the state. But what if we want to react on nested properties of the state, for example modules.geotools
? Seems like there should be a possibility to call a store.select('modules.geotools')
, as putting everything on the first level of the global state seems not to be good for overall state structure.
Update
The answer by @cartant is surely correct, but the NgRx version that is used in the Angular 5 requires a little bit different way of state querying. The idea is that we can not just provide the key to the store.select()
call, we need to provide a function that returns the specific state branch. Let us call it the stateGetter and write it to accept any number of arguments (i.e. depth of querying).
// The stateGetter implementation
const getUnderlyingProperty = (currentStateLevel, properties: Array<any>) => {
if (properties.length === 0) {
throw 'Unable to get the underlying property';
} else if (properties.length === 1) {
const key = properties.shift();
return currentStateLevel[key];
} else {
const key = properties.shift();
return getUnderlyingProperty(currentStateLevel[key], properties);
}
}
export const stateGetter = (...args) => {
return (state: AppState) => {
let argsCopy = args.slice();
return getUnderlyingProperty(state['state'], argsCopy);
};
};
// Using the stateGetter
...
store.select(storeGetter('root', 'bigbranch', 'mediumbranch', 'smallbranch', 'leaf')).subscribe(data => {});
...
select
takes nested keys as separate strings, so your select
call should be:
store.select('modules', 'geotools')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With