Home » Angular 2 » NgRX 4 Lazy Loading

NgRX 4 Lazy Loading

This past week I took a stab at implementing NgRX 4 Lazy Loading and learned a few things that weren’t obvious to me.  I thought you’d want to hear about them.

Photo via Visualhunt.com

If you haven’t already upgraded to NgRX 4, you’ll want to do that now.  Everything else in this post assumed you’ve already done that.

Always Import forRoot() calls

I think this is probably pretty obvious, but just for the record, you’ll need to make sure you’ve already imported the root store and effects module in your main application.

imports: [
    StoreModule.forRoot({}),
    EffectsModule.forRoot([]),
...
If you have reducers or effects that apply at this level, you should add them in here, but even if you don’t have any reducers or effects at the root level of your application, you need to make these two calls.  Otherwise, the forFeature() calls won’t be able to access the root store or effect location to add in the reducers and effects for the feature.

Not Just for Lazy Loading

We have a set of components that have loose dependency on NgRX stuff.  That is, strictly speaking they are dumb components.  But to get most of the functionality, we’ve hooked them up to NgRX.  We wanted to make these sets of functionality shareable by placing them in their own project.  So, in the module that declares and exports each component, we also put the appropriate forFeature() imports for the store and effects the modules depend on.  To be save, I imported the component’s module after the forRoot imports in my main application.

AppState vs FeatureState

You’ll remember from previous NgRX articles that you’ll typically use an interface call AppState to define the structure of your store for your application.  For reasons we’ll get to later, you are going to want to create a separate interface for each set of feature reducers you are loading.  In my case, it was necessary because the feature stores couldn’t know what application they would be implemented in.  But as it turns out, you are going to need to do this anyhow.

Feature Name as AppState Property

When you add a feature reducer, you’ll need to supply a name as the first parameter.

imports: [
    StoreModule.forFeature('featureName', featureReducers),
    ...
]

This featureName becomes the name of the store entity you’ll need to select to get to the store entities in your feature reducers.

Say you have a feature named ‘featureName’ as we’ve coded above and your featureReducer object has a feature property named ‘sub’.  Not super original, but it will do for an example.

To select ‘sub’ from your store, you would use code that would look something like this:

store.select(x => x.featureName.sub);

This means that if you want to strongly type your selection process using AppState, you will need to define a field in your AppState interface as ‘featureName’ that is typed as the State interface for that feature.  Let’s call that FeatureState.

export interface FeatureState {
    sub: SubModel;
}

export interface AppState {
    featureName: FeatureState
}

Which then lets us write our select code like this:

store.select((x: AppState) => x.featureName.sub);

How This Differs from What I was Expecting

Now, when I started out adding in the features, I was expecting that the feature reducers, and therefore the store entities, would get added to the store at the top level like everything else.  That the feature name was somehow just a key so we didn’t end up doing that more than once.  The code could be so much cleaner if we didn’t need that parameter.  But I see now that by doing it this way we reduce the possible collisions between store names in different features.

Anyhow, starting off with this assumption, I thought that we would extend all of the feature states to create our AppState.

export AppState extends FeatureState1, FeatureState2, etc ... {
}

But, that’s not the case.

What’s Still Missing.

I really like how NgRX implement the Flux/Redux pattern.  But, there is one piece still missing.

I would love to be able to create a “private store.”  This would be a store that I could attach to a specific module.  It would not care if NgRX had been implemented in the rest of the application or not.  And, by having this private store, we could create components that implemented the NgRX pattern internally.  Something to consider for NgRX 5 maybe?

 

Other post in Angular 2
Summary
NgRX 4 Lazy Loading
Article Name
NgRX 4 Lazy Loading
Description
This past week I took a stab at implementing NgRX 4 Lazy Loading and learned a few things that weren't obvious to me.  I thought you'd want to hear about them.
Author
DMB Consulting, LLC

About Dave Bush

Dave Bush is a Full Stack ASP.NET developer. His commitment to quality through test driven development, vast knowledge of C#, HTML, CSS and JavaScript as well as his ability to mentor younger programmers and his passion for Agile/Scrum as defined by the Agile Manifesto and the Scrum Alliance will certainly be an asset to your organization.

Leave a Reply

2 Comments on "NgRX 4 Lazy Loading"

Notify of
avatar
Sort by:   newest | oldest | most voted
Yngve Bakken-Nilsen
Guest

It seems you’ve been missing some key points here. You should take a look at this:
https://github.com/ngrx/platform/blob/master/docs/store/selectors.md

and also you’re not supposed to add the feature-names to your appState, as the forFeature(‘featureName’, reducer) will handle this in conjunction with the createFeatureSelector mentioned in the doc above

wpDiscuz