Home » Angular 2 » How to Really use NgRX — Better

How to Really use NgRX — Better

Several weeks ago, I introduced NgRX as a way to manage state in your Angular applications.  You should think of that article as a basic “getting started” article.  What I want to cover today is a better way of organizing you code that solves several problems with using NgRX the way I outlined in that article.

It isn’t so much that what I wrote is “wrong” just that it is incomplete.  Today’s post is …

How to Really use NgRX Better
Photo credit: m01229 via Visual hunt / CC BY

 

… the rest of the story.

Problems We Need to Solve

The first problem we need to solve is that we want to be to subscribe to our data without using Magic Strings.  We solved that several weeks ago by writing some extra code.  But there is a much easier way.

The second problem we need to solve is that we want to prevent any of our code from mutating any part of any table in our store.  When we set up our reducers a couple of weeks ago, I mentioned that we wanted to make sure that we always returned new data.  But, how can you be sure you’ve covered all of your bases?

And finally, it would be great if we could subscribe directly to data within a table rather than only being able to subscribe to data at the table level.

As with most of my code, I’m going to assume you are using the Angular CLI.

Eliminate Magic Strings Without Extra Code

In the last article, I showed a lot of convoluted code to eliminate using magic strings in our application.  That was before I learned that we don’t need to use magic strings to access our store entities.

Check this out.

Instead of using:

store.select('magicString');

to get an observable to our store entity, we can use:

store.select(x => x.magicString);

and we will get back the same observable.  Everything else remains the same.

The only thing you need to do to make this work is that you need to make sure you have defined an interface that describes the various entities in your store.  When you inject your store into your component, or other object, you’ll specify this interface as the type the store represents.

Sub Entities

But wait!  There’s more.

Let’s assume for a second that our entity that we are listening to is an object with multiple properties rather than a single value like we’ve been working with.  You can create an observable on any sub-entity in your store by just drilling down.

store.select(x => x.magicString.childEntity);

This allows us to combine entities together into one entity where that makes sense instead of having a flat model just to support the ability to create an observable on a specific value.

Now that we are using our interface to describe our entities, we don’t need all of the wacky code we placed in our app.stores.ts file.  So, instead of this:

All we need now is this:

Object Mutation

There is a library you can add to your application called ngrx-store-freeze that, once you’ve implemented, will make all of your fields read-only.  By doing this, every time your code tries to modify a field that is part of your store, an exception will get thrown.

The trick, of course, is getting it implemented.

The first thing you are going to need to do is to install the package.

npm install --save-dev ngrx-store-freeze

Now move over to your app.store.ts file.  We left it like this in the original article.

To get the package installed, you will need to import it

import {storeFreeze} from 'ngrx-store-freeze';

And here we are going to deviate from the instruction on the npm site.

You see, the instructions worked before TypeScript got updated.  Now we need to write a bit more code.  Plus the variable they use for detecting if we are compiling for production or not isn’t the variable we are going to use.

The code we want to use now looks like this:

One of the first things you’ll notice is that we are using combineReducers instead of passing the reducers constant to provideStore() directly.  When we pass in the constant as we’ve been doing, provideStore() calls combineReducer() for us.  Now that we want to add storeFreeze, we are calling it ourselves.  It doesn’t matter which way you do this, essentially the same thing happens either way.  So, our productionReducer now points to our main reducers constant, somewhat indirectly.

The second thing you’ll notice is that we are using compose to merge storeFreeze and combineReducer together.  We pass in our reducers constant to the resulting function.  devReducer points to a new meta-reducer that also has storeFreeze as part of it.  The end result is that if you try to modify anything in your store directly, an exception will be thrown.

The reason this works is because we are taking advantage of the environment variable that the Angular-CLI provides for us called ‘production’.  This variable is true when we compile for production mode and false while we are developing.  Now, freeze works for development, but not in production.  There is no need to worry about your code slowing down in production mode.  In my experience, it isn’t noticeably slower anyhow.

Next Steps

Now that we have a solid understanding of how state management works, how do we put this together with displaying the data on our screen?  That’s a topic for a future post.  Don’t forget to subscribe to the news-letter so you don’t miss it.

 

Other post in Angular 2
Summary
How to Really use NgRX -- Better
Article Name
How to Really use NgRX -- Better
Description
The second in a multi-part article on how to use NgRX correctly in your code
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

Be the First to Comment!

Notify of
avatar
wpDiscuz