NgRx Tips — Part 1 — Module Setup with Lazy Loading

John Youngers
Youngers Consulting
2 min readJan 25, 2018

If your Angular project is tuned towards lazy loading with isolated modules that are loaded on demand, where these modules define their own sections of state via StoreModule.forFeature(...), you may have your root module defined like so:

StoreModule.forRoot({} as any, { initialState: getInitialState })

Where we initialize the application with the full state, however, we aren’t providing any reducers. The issue with this approach is if the reducers aren’t available, then any feature that has yet to be loaded will be dropped from the state as actions are dispatched.

For example, let’s say our application has a “Settings” area and a “Todos” area, if we initially land in the “Todos” area of the application without visiting “Settings”, that part of the state will be removed on the first dispatched action, since there isn’t a reducer available yet to handle that feature’s state:

the settings section was removed since the feature hasn’t loaded yet.

One way to prevent this (without referencing all reducers in the application), is to initially set all features to use a default reducer that simply takes in the current state and returns it:

We then update the NgRx initialization like so:

StoreModule.forRoot(initialReducerMap, { initialState: getInitialState })

As your features are loaded, they’ll replace the default reducer. Until then, they’ll return the initial state on any dispatched action to prevent those features from dropping out of the state:

“settings” is now retained

As you continue development, if a new feature is added and the ApplicationState interface updated, it should result in a compile error until the initialReducerMap has been updated as well .

Your store selectors can then safely assume the feature state sections will always be there without needing to do undefined checks.

In the next article I’ll go into further detail on selectors and testing.

--

--