Reputation: 437
I am dispatching a Ngrx action in my (root) App module (in AppComponent), which should be handled through an effect but this effect is not being trigged. The effect is declared/implemented in some other lazy-loading angular module and I am presuming that lazyloading could be the clue.
I suppose that since my lazy module has not been loaded yet, there is no way for angular to know that the effects is there to be picked up, although the effect is declared in my list of effects (EffectsModule.forFeature(...). I am sure that the lazyloading module is not loaded, because the route which triggers the lazy loading of the corresponding module has not been triggered yet.
To verify/validate my assumption I made the lazyloading module eager by adding the module to my root module's import and the action was detected and handled this time by the effect.
Is this a lack of design in my app or is there a pattern/best practise for dealing with this situation?
Upvotes: 0
Views: 450
Reputation: 151
To expand on timdeschryver's answer some:
Lazy loading strategies - Eager loading does introduce additional load time when the user first pulls up the application. One of the alternatives is Preloading Module. This method loads only what is needed by the user when the page is first loaded, and then begins to load additional modules in the background unbeknownst to the user. This might solve your problem, depending on when certain actions are dispatched and when you expect the Effect to be available.
Root State
I've used this in the past:
src/
app/
// main, necessary application components/services
core/
// all lazy loaded modules
features/
// shared components/directives/etc
shared/
// all ngrx-related state
root-state/
root-store.module.ts
root.effects.ts
feature1-state/
feature1-state.module.ts
feature2-state/
feature2-state.module.ts
In the above scenario, root-store.module.ts
imports all feature state modules, registers all feature Effects.. basically handles everything state related. Then, in app.module.ts
you only have to import RootStoreModule. This also increases the initial load time (slightly), but ensures all of your state/effects are available from the start. (All interaction with state data is done via Facade services in feature modules that get lazy loaded)
Lastly, after digging a little, I found this blog post which introduces the concept of using a service to programmatically call import('../path/to/lazy/module').then(m => m.FeatureModule)
just like you would use in a Routing module. I haven't tried this, but if it works as described that could easily be added as an Effect for lazy module loading on demand.
Upvotes: 0
Reputation: 15505
Your findings are correct. An Effect is only registered when the lazy loaded Angular module is loaded. Also fyi, the same stands for feature reducers.
In most of the cases this means that you need to lift that state up to the root module. You can do this by eagerly loading the module, this means that the Angular components are also loaded. Or you can move the effect/reducer to the root state.
Upvotes: 1