Reputation: 4595
I have two angular modules: main and feature:
Main / root module:
@NgModule({
imports: [
StoreModule.forRoot({router: routerReducer}),
EffectsModule.forRoot([...]),
...
],
declarations: [],
...
})
export class AppModule {}
Feature module:
@NgModule({
imports: [
StoreModule.forFeature('feature', {someValue: someValueReducer}),
EffectsModule.forFeature([...]),
...
],
declarations: [],
...
})
export class FeatureModule {}
I need to access 'feature' slice of data in main module to conditionally display / activate application tab based on data stored in feature
module.
(In other words I need a global / shared piece of state accessible by all modules main and any feature module.)
Currently I can't do that since there is no feature
state in main AppState
:
export interface AppState {
router: RouterReducerState<RouterStateUrl>;
}
And typescript indicates error this.store.select('feature')
since there is no feature
key of main store AppState
.
Using selector
: this.store.select(selectFeatureValue)
I am getting runtime error:
export const selectFeatureModule = createFeatureSelector<FeatureState>('feature');
export const selectFeatureValue = createSelector(selectFeatureModule ,
(state: FeatureState) => state.someValue);
I am getting error in main AppComponent:
TypeError: Cannot read property 'someValue' of undefined
Upvotes: 12
Views: 12006
Reputation: 191
I think, this is a valid question at least partly. Imagine the following structure:
appState
├── coreState
│
├── lazyModuleSate1
│ ├── subStateA
│ └── subStateB
│
└── lazyModuleSate2
├── subStateA
└── subStateB
coreState may hold common info about user, session...
Reducers of lazy modules may need to access such common state while processing actions.
BUT
Reducer(s) of the core module see only coreState.
Reducers of lazy modules (defined with ActionReducerMap) see only their own subState. It is nice and clean for most of the cases, but sometimes, actions should be processed on condition of coreState. There would be no problem, coreState is always in the store.
Metareducers defined in the lazy modules see ONLY their own lazyModuleState. It is still useful, to handle interconnections between subStates, but they do not help with coreState - lazyModuleSate relations.
Only global metareducers defined at app level see the coreState. It is possible to handel actions here, although very ugly.
Upvotes: 10
Reputation: 4595
My solution:
Upvotes: 5
Reputation: 15221
In my opinion, that pretty much defeats the purpose of both: lazy loaded modules and lazy loaded stores.
You should probably rethink your design. Its usualy vice versa, that you need main state in your feature module and that's fine since you can't have feature module active without main one but vice versa is a bit odd.
Now, that being said, the main idea of lazy loaded store is that you don't have feature store keys in your main store but they are added afterwards, during the application lifetime as they are needed. So, what you can do is import your feature reducer into main module component where you need it and select from feature reducer directly. But again, its a question if that's something one would want to do. I wouldn't.
I would rethink the design and things i need in main module i would put into main reducer/store.
Upvotes: 11