0% found this document useful (0 votes)
497 views

NGRX Tutorial Series

This document summarizes a 5-part tutorial series on NgRx (Reactive Extensions for Angular). It includes an introduction to NgRx and Intertech, the company providing the tutorial. It also provides summaries of the first two chapters which cover adding NgRx to an Angular project using schematics and generating actions, reducers, and effects. Additional resources like a code review checklist and consulting are also advertised.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
497 views

NGRX Tutorial Series

This document summarizes a 5-part tutorial series on NgRx (Reactive Extensions for Angular). It includes an introduction to NgRx and Intertech, the company providing the tutorial. It also provides summaries of the first two chapters which cover adding NgRx to an Angular project using schematics and generating actions, reducers, and effects. Additional resources like a code review checklist and consulting are also advertised.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 37

NgRx Tutorial     

5-Part Series

Page 1 of 37
Table of Contents

1. Cover

2. Additional NgRx Resources

3. Introduction

4. Quickly Adding NgRx to Your Angular 6


Project

5. Actions, Reducers and Effects

6. Accessing State in the Store

7. Add State to Feature Module

8. Add Router Info to State

Page 2 of 37
NgRx Code Review Checklist
You've downloaded our NgRx tutorial
series, a great first step to ensuring that
your getting the most out of NgRx.  The
second step? Download our free NgRx
code review checklist.  A helpful
resource to help you successfully
review your NgRx code.

DOWNLOAD NOW

NgRx Free Project Consult


Serious about ensuring your
NgRx project is on the right track? 
For a limited time, Rich Franzmeier,
the author of the NgRx Tutorial
Series and Checklist, will be
offering short one-hour consults. 
Limited available slots. Visit the link
below to learn what you can expect
and to reserve your spot.

SIGN UP TODAY

Page 3 of 37
Introduction

NgRx (Reactive Extensions for Angular) is becoming increasingly popular in the


Angular community.  It is a great way to manage state using the redux pattern
and keep your application scalable.  
This series, by Intertech developer Rich Franzmeier, is for beginners and those
experienced with NgRx alike, walking readers through the basics of NgRx while
also diving into more advanced concepts. 

About Intertech
Founded in 1991, Intertech delivers technology training and software
development consulting to Fortune 500, Government and Leading Technology
institutions. 
Learn more about us. Whether you are a developer interested in working for a
company that invests in its employees or a company looking to partner with a
team of technology leaders who provide solutions, mentor staff and add true
business value, we’d like to meet you.  
www.intertech.com

Page 4 of 37
Chapter 1: Quickly Adding NgRx to
Your Angular 6 Project

NgRx (Reactive Extensions for Angular) is becoming more and more popular in the Angular
community.  It is a great way to manage state using the redux pattern and keep your
application scalable.  When I first started using it, my biggest complaint was that it was a lot of
typing basically the same thing over and over.  Thankfully, the NgRx team addressed this with
@ngrx/schematics.  This package enhances the Angular CLI with new commands for NgRx.  For
example, to create a new actions file, simply type:  ng generate action ActionName
This first chapter is meant to help you get up and running quickly with NgRx by using the
@ngrx/schematics package.  It is using NgRx version 6.01 so if it doesn’t look the same to you, it
could be things have changed.  No knowledge of NgRx is necessary to read this post and setup
your project!
 

UPDATE
Note:  Use the “ng add” command to achieve most of the things done using schematics in this
article. Run these commands for an existing project that doesn’t have NgRx:

After this completes, the only things necessary to do in this article will be the following:
Setup – under here, you may want to install the rest of the ngrx tools
NgRx Startup Code
Store Command – under here, you’ll have to add the “reducers” folder to a “store” folder to
get the same structure as in the post
Effect Command – under here you’ll have to add the “effects” folder (which wasn’t added for
you) to a “store” folder to get the same structure as in the post

Page 5 of 37
Setup
I start by creating a project using the standard Angular CLI command:
ng new ngrx-tutorial
This will give you the standard Angular starter project.
Now let’s install the NgRx schematics package:

Install the rest of NgRx:


 

NgRx Startup Code


Now that the project is setup and we have NgRx installed, we are ready to see the power of
Schematics.  Before we start running schematic commands, we will register it as the default
collection in the Angular project by using this command:
ng config cli.defaultCollection @ngrx/schematics
Running this command adds the following to the angular.json file:

“cli”: { 

“defaultCollection”: “@ngrx/schematics” 

Store Command
Now we can run the ‘store’ command:
 

Page 6 of 37
This command did the following:
Created a ‘store’ folder at the app level
Created a ‘reducers’ folder in the ‘store’ folder
Created an ‘index.ts’ file in the ‘reducers’ folder
This is the main reducer file for the root store (as opposed to feature store(s))
which contains:
State interface definition (empty)
reducers – ActionReducerMap (empty)
metaReducers – MetaReducer<State>[]  (empty)
Imported the following to the AppModule:
StoreModule.forRoot(reducers, { metaReducers }),
Prepares the app for reducers and metaReducers
!environment.production?StoreDevtoolsModule.instrument() : []
Instruments the app for development

If I run “ng build” now, I get an error:


ERROR in src/app/app.module.ts(8,29): error TS2307: Cannot find module
‘../../../environments/environment’.
Ok, so the schematics aren’t perfect.  I think this is because I put the index.ts file two levels
deep from ‘app’.  To fix this simply go to app.module and remove two levels of relative path for
this import:
import { environment } from ‘../../../environments/environment’;
This should do the trick:
import { environment } from ‘../environments/environment’;
 

Effect Command
The next command to run is the “effect” command.  It’s purpose is to get our first effect
registered with the application so it is ready to go.
This is the command to run:

Page 7 of 37
 

This command did the following:


Created an “effects” folder under “store”
I like to keep actions/effects/reducers under the “store” folder
Added the app.effects.ts file in the “effects” folder
It is simply an effect with a constructor that has the Actions injected into it
Imported the following to the AppModule:
EffectsModule.forRoot([AppEffects])
Did not create a spec (unit test) file – just leave out “–spec false” if you want that file

Conclusion
Getting up and running with NgRx is now quicker than ever with the @ngrx/schematics
package.  Without knowing anything about NgRx, you can set up your project for it using best
practice code so that your team is ready to start using NgRx.  In the next chapter, I'll cover some
of the other schematics commands to keep you productive as you code NgRx in Angular.

Page 8 of 37
Chapter 2: Actions, Reducers and
Effects

In the first chapter, I wrote about setting up NgRx in your Angular 6 application.  Now it’s time
to focus on actions, reducers and effects.  These are the heart and soul of your NgRx code and
will be the ones you use most on a day to day basis.  You will learn what they are, how to
generate them, and how they work together in an Angular application.
The NgRx store is an implementation of the Redux pattern.  Learn more about that here. 
Actions and reducers are a big part of the redux pattern.  Effects are NgRx constructs to help
with asynchronous operations.

Actions
Actions are objects that extend the NgRx Action class with a ‘type’ property.  They have an
optional ‘payload’ property (naming is up to you but the standard is to name it ‘payload’) for
sending in data to the effect/reducer and are dispatched by the store to either run an effect or
change state in a reducer.  So you can see that actions aren’t all that complicated but NgRx
schematics does generate action files for you and can help you standardize them in your
project.
To generate an action file, run this command:
ng generate action store/actions/auth
This generates the following file:

Page 9 of 37
Notes:
It generates a sample action
Notice the error – LoadsAuths on the last line should be Auth (or the Auth action should be
named LoadAuths – better yet)
This is an error with NgRx schematics but is no big deal as it gets you a
template to follow
The action constants are stored as an enum (AuthActionTypes)
The action class has a type (you can add optional payload)
The AuthActions type helps you to define all of your actions for Auth as a type – in the
reducer you’ll see why this is important
 

Dispatching the Action


Actions live to be dispatched.  Reducers and effects just wait until an action is dispatched so
they can do their job.  But how are they dispatched?
To dispatch the action we just created, you would typically do that from your component.  Here
is the typical code you need:

Notes:
Imports:
Store from @ngrx/store
import * as fromRoot… – this is where the main State interface lives in the
index.ts file
import * as authActions… – this is where our LoadAuths actions live

Page 10 of 37
Notes (cont.):
Inject the store
In the constructor, inject the store as shown in the code
When it’s time to dispatch (sometimes in ngOnInit, sometimes from a button click, etc.), run
this command:
this.store.dispatch(new authActions.LoadAuths());

Reducers
Reducers are pure functions that are the only ones that can change state.  They aren’t really
changing state but making a copy of existing state and changing one or more properties on the
new state.
To generate a reducer file, run this command:

This generates the following file:

The reducer file adds:


The State for the reducer – this state is added to the main state (see code below)
Initial state which are your starting values
A reducer function that will be added to the main reducer (see code below)

Page 11 of 37
The main reducer file (index.ts) was changed to this:

Notes:
It added import shown above
It added auth: fromAuth.State; to the State interface
It added auth: fromAuth.reducer to the reducers constant
 

Add Action to Reducer


Now let’s see how actions and reducers fit together.
This is what I’ll do:
1. Add the ‘userName’ property to the auth reducer’s State
2. Add a ‘SetAuth’ action which will set the userName property on State (payload is userName)
3. Update the reducer to handle this new action
Updated auth.actions.ts file:

Page 12 of 37
Updated auth.reducer.ts file:

Notes:
The userName property is added to State and initialState (not necessary for initialState of
course)
In the ‘reducer’ function, the action is changed to authActions.AuthActions (which is the
exported type AuthActions)
The case statement is added for SetAuths
I like to add a function to handle each action so the switch doesn’t get so
huge and ugly
The handleSetAuths function returns a new copy of state
The …state spread operator basically copies existing state
userName: action.payload then overwrites the userName property of State
(which is the only one at this time, but more should be added)
 

Page 13 of 37
Effects
Effects allow us to handle asynchronous operations in NgRx.
Most times this will be calling an API
The resulting data should be stored in state by returning an action for the reducer
Effects always return one or more actions (unless you decorate @Effect with {dispatch: false})
You can inject services into your effects as well so if you need to access those in NgRx,
effects are the place to do it
To generate an effect file, run this command:

This generates the following file:

It also updates your app.module.ts file:

The main thing the schematics generated here is EffectsModule.forRoot([AuthEffects]).  This


registers our new AuthEffects class with NgRx so that it starts to listen for dispatched actions.
 

Page 14 of 37
Create an Effect
The generated effect file doesn't give you a skeleton effect to follow like the action file does, so
I'll explain how you would do that here.
Here is the final effect (see notes below for explanation of how to create it):

Notes:
Decorate the effect with @Effect()
Name the effect using camel case of the action name and end with $ to denote it is an
Observable (loadAuths$)
The type of this variable should always be Observable<Action>
The 'ofType' function is what is triggering this effect - whenever LoadAuths is dispatched as
an action, this effect will run
Note it is using the string LoadAuths here and not the action class
Use http to do whatever you need to do, in this case log the user in and return the user
name
Return from the map a SetAuths action with the userName
This will automatically dispatch the SetAuths action to the
reducer to update the userName on state
If you want to return multiple actions, return an array of actions
 

Page 15 of 37
Project
So, over the last two chapters, this is how the project looks with NgRx:

I like to have the actions, effects and reducers in their own folder under a 'store' folder so that
they are easy to find.  I have seen it done other ways - without a 'store' folder for example - but
this is my preference.  In a future chapter, I'm going to talk about feature modules so I'll start
having one 'store' folder for each feature.  So the pattern will reproduce itself many times in the
project.
 

Conclusion
In this chapter, you learned how to generate actions, reducers and effects using NgRx
schematics.  You also learned what actions, reducers and effects are for and how they work
together to help you to manage state using NgRx in your Angular 6 application.  In the next
chapter, I plan to show you how to access the state from your application.

Page 16 of 37
Chapter 3: Accessing State in the Store

In this chapter, we continue our NgRx Tutorial by showing how to access state in the store by
using selectors.  It will complete the circle that started with dispatching an action, then an effect
doing asynchronous work and finally the reducer updating state in the store.  The missing piece
is accessing that state in a component so that it can be displayed or used in various ways.  For
purposes of demonstration, I will be simulating a login in my ‘auth’ slice of state and store a
user name and friendly name.  This friendly name will be shown to the user on the welcome
page.  I’ll of course use the Star Wars API to get the name.
This is the goal for the page output:

Code:  github

Add Welcome Component


First I’ll add a welcome component that will show the message.  Of course use the
@ngrx/schematics package to do it.
To generate a container, run this command:

This basically is the same as ng g component but adds the store to the constructor:
We’ll get back to this component later.  First we need to understand how to access state from
the store using selectors.
 

Page 17 of 37
Add Selectors to the Auth Reducer
Before getting to selectors, I’m going to update the auth reducer as shown:

Notes:
Added ‘friendlyName’ to State – this will be shown on the welcome page
Updated handleSetAuths to take in more than just userName as payload (actions were also
updated with a SetAuthsPayload interface with userName and friendlyName as properties)

Auth Selectors
Now I’m ready to add selectors to this reducer.  Selectors help us get at the data in the store by
using pure functions and keeping most of the logic on the store instead of in the components. 
The first step with selectors is to add selectors in your reducer for each property of state as
follows:

These are just pure functions that take a State parameter and return a value on state.  This will
be used in the main reducer file to create the selectors there.

Page 18 of 37
Selectors in the Main Reducer (index.ts)
It’s convention to put the selectors that everyone uses in the main reducer.  For feature
modules, you’ll do it in the feature module’s main reducer (that’s a future post).  These selectors
are the way for the consumer (usually components) to access a slice of state in the store.  It
seems like a lot of busy work (and it is) but we do it this way so that it can be easily unit tested in
one spot (the reducers) and easily consumed from the components.
Here are the auth selectors:

Notes:
createFeatureSelector and createSelector are imported from ‘@ngrx/store’
selectAuthState:  this creates a feature selector of type fromAuth.State (the state in the auth
reducer)
The ‘auth’ string must match the property in state
This will be used to get the auth State for the upcoming createSelector
functions
getUserName:  this creates a selector using selectAuthState and our getUserName selector
we defined above
getFriendlyName:  this creates a selector using selectAuthState and our getFriendlyName
selector we defined above
For a thorough look at selectors in NgRx, take a look at Todd Motto’s blog post on this topic.
 

Page 19 of 37
Add Friendly Name to the Welcome
Component
Now we are ready to access our friendly name that lives in auth state from our welcome
component.
This is our updated welcome component:

Notes:
First, define a ‘name$’ Observable<string> property
The html will reference this
Now, populate the name$ with this.store.select(fromStore.getFriendlyName)
This is using our selector created in the main reducer
Whenever this value is updated, it will automatically update the component

This is the html portion:

Notice the ‘async’ pipe.  That is needed for Observables.  It will handle the unsubscribing so
there’s no need for you to do it.
This code makes it super easy to access state and show it on your page.  As an alternative, you
could have accessed state in this way:

This is problematic, though, because you have to do null checking and other work to ensure
you don’t get errors accessing the state.  With the selector approach, that can be taken care of
in a centralized place and heavily unit tested.

Page 20 of 37
Update the Effect to get Star Wars Name
One last thing to do is update the LoadAuths effect so that it gets us person one from the Star
Wars API, namely Luke Skywalker.

Notice how SetAuths is now passing an object with userName and friendlyName.  This will call
the SetAuths reducer and update state.  Friendly name will finally appear on our welcome
component.
 

Conclusion
Accessing state in NgRx is extremely important and is what the components (mainly) consume. 
It is done using state selectors that we define in the reducers.  These selectors access a slice of
state and should be fully unit tested.  With the knowledge gained in these first three chapters,
the reader should be able now to develop an Angular app using NgRx for state management. 
The final piece of this puzzle is setting up feature modules with their own state and all that goes
with that.  That will be tackled in upcoming chapters.

Page 21 of 37
Chapter 4: Add State to Feature
Module

Feature modules are Angular modules that group a bunch of components/services, etc. into a
module.  This allows us to separate concerns nicely.  Most likely, you’ve dealt with feature
modules if you have 1 month experience in Angular.  Since feature modules can be lazy loaded
and because they are separate from the main app module, NgRx does things a little differently. 
In this chapter, I plan to describe how to setup a lazy loaded feature module with NgRx.
The code is on github.
 

Create a Feature Module


Staying with the Star Wars API theme, I’ll create a “Starships” feature module that will display a
list of the first ten starships in the Star Wars universe.
This is the Angular CLI command to create the module:
ng g module starships
This creates the following module code:

Create the NgRx Feature Module Code


Before creating the component in the module to show the starships, I’m going to generate the
NgRx actions/effects/reducers using the following NgRx Schematics command:

Page 22 of 37
This does the following:
Creates actions, effects and reducers folders with their respective files
ships.actions.ts, ships.effects.ts, ships.reducer.ts
Updates the starships module we created first thing as shown:

The following were added:


StoreModule.forFeature(‘starships’, fromShips.reducer)
EffectsModule.forFeature([ShipsEffects])
So you can see that our feature module has it’s own module setup but “forFeature” instead of
“forRoot” as in the app.module.
Also note that instrumentation wasn’t setup in the feature module, that is only required in the
root module (app.module).  For a refresher, this is the setup of instrumentation in the
app.module imports:

This gives us the ability to view state from a Chrome browser extension called Redux DevTools.
I’m also going to move the actions, effects and reducers folders under a “store” folder.  I do this
so it’s easier to find all things NgRx within the feature module.
Last thing is to fix up the actions file because this is how it was generated:

As you can see there are some problems here.


LoadShipss – problem with plurality
Ships action should be LoadShips

Page 23 of 37
Reorganize the Starships Reducer
The way it’s setup now, the ships reducer is setup to handle only one reducer in the feature
module.  That’s obviously not ideal so a little reorganization is in order.
First, I add some state to the ships reducer:

Now I’m going to create an index.ts file in the starships/store/reducers folder:

These are the important points:


Created interface StarshipsState – this will hold all of the different states in the different
reducers we may create in this feature module
Created an ActionReducerMap of StarshipsState – this will define the reducers that
correspond to the properties in StarshipsState
Created interface State that extends root or main State – this is the one that will be referred
to in our components in this feature module and will allow us to see state from the
app.module level
Note you still can’t see state from other feature modules
We won’t add any more code to this state as all additional state/reducers will
be added to StarshipsState

Page 24 of 37
Create Component to Show Starships
Now we are ready to create the component to show the starships and inject the store into the
component.
I’ll use this NgRx schematics command to generate a container:

This does the following:


Creates the ship-list component
Injects the store into the component (using our State that extends root State)
Adds the component to our starships.module declaration
Here is the HTML for the component:

The user$ variable is there to use the root part of state that we previously had retrieved (Luke
Skywalker)
The starships$ variable holds the results of state so initially it will be empty and then it will
load once state changes

Page 25 of 37
And then the component code:

Dispatch the LoadShips action to load the ships using the Star Wars API in the effect (see
code below)
Use the fromStore.getAllShips to get the ships from our feature module…here’s how this is
setup in the feature module index.ts reducer:

The ‘starships’ in the State interface must match the ‘starships’ in the selectStarshipsState
selector
And it must match the forFeature declaration in the feature module
Note that the “createFeatureSelector” command doesn’t match (as of 8/18/2018) what is in
the NgRx example app
That’s because it is a future thing that we don’t yet have access to (see Stack
Overflow)
selectShips gets the ‘ships’ property of StarshipsState
getAllShips then just gets the allShips property of fromShips.State
 

Page 26 of 37
LoadShips Action in the Effect
Here is the LoadShips action in the effect (which will call the Star Wars API to get the first ten
ships):

SetShips will then call the reducer function to update state as shown in ships.reducer:

Page 27 of 37
Redux DevTools to View State
I mentioned Redux DevTools, a Chrome extension, earlier.  Let’s take a look at it now.  It is a
useful tool when developing to see what is actually in state and the actions that got it that way.
Here is a screenshot of it for when we view the starships:

Notice that we have selected “[Ships] Set Ships”, that’s the action that calls the reducer to
change state
Load Ships is called before – that one got the ships from the API
“starships” is our feature name
“ships” is the property on StarshipsState
“allShips” is the property on the ships.reducer State
 

Page 28 of 37
How the Page Looks
If you are curious, here is my award-winning web page for showing the starships:

Conclusion
So that was quite a lot!  But we were able to do the following:
1. Add a lazy loaded feature module (see the code on github for how to lazy load a module)
2. Add NgRx state to it
3. Prepare for future expansion within the feature module by reorganizing reducer code
4. Create a cool component using NgRx state
5. View the contents of the state in the browser using Redux DevTools
After these four chapters, you should be getting pretty good at using NgRx to manage state in
an Angular application.  I’m sure most projects are using feature modules these days and being
able to manage state with NgRx is a valuable skill to learn.

Page 29 of 37
Chapter 5: Add Router Info to State

Adding Angular router information to state is very important for NgRx.  Why, though, does it
matter if the Url, parameters and query parameters are stored in state?  Good question!  This
chapter aims to answer the question.  I’ll be building upon the code that has been written in my
previous four posts on NgRx.  I plan to add a starship detail page to the app which features the
Star Wars API.
The code is on github.

Add Custom Router Serializer


The first thing I’ll do is get the router information into state.  There is some pretty boilerplate
code that we’ll add to our root reducer to make that happen.  You can find it in the NgRx docs
here.  Note that the code there isn’t perfect and I’ll point that out as we go.
In our app/store/reducers/index.ts file, let’s add this code:

Page 30 of 37
Notes:
RouterStateUrl is an interface which defines what we want to store about the router
It can be anything that is on RouterStateSnapshot (however, there are some
things on RouterStateSnapshot that are not immutable and will break NgRx
store freeze)
The CustomSerializer class will basically be the code that copies things from the
RouterStateSnapshot into our RouterStateUrl interface and returns that
To get this code to run, you’ll have to add the following code to the
app.module:

Import the StoreRouterConnectingModule


Note that this is where the NgRx docs’ code has it wrong (at least as of
9/9/2018) – there is no need for the forRoot({serializer: RouterStateSerializer})
– in fact it won’t compile if you have it
Provide the RouterStateSerializer to be our CustomSerializer

Add the Router Info to State


Now that the CustomSerializer is in place, we are ready to add it to state.  Back in the
app/store/reducers/index.ts file, we’ll add a new ‘router’ property to State and reducers:

Page 31 of 37
Notes:
Add the “router” property to the State interface
RouterReducerState is imported from @ngrx/router-store
The generic piece here is our RouterStateUrl interface defined previously
Add the “router” property to the ActionReducerMap
routerReducer is imported from @ngrx/router-store
 

Add Router Info Selectors


Lastly, I’m going to add selectors so we can access this router info in our application.  Without
this piece, at this point, we would still have a win by putting router info in the state because it
gives us the ability to do time-traveling using the Redux DevTools in Chrome.  I’ll show you this
later on.
Here are the selectors in the app/store/reducers/index.ts file:

selectReducerState creates our feature selector “router” which matches the property name
on State and the reducers map
getRouterInfo returns the RouterStateUrl interface we defined initially with the url, params
and queryParams – which is what we care most about

And that’s all there is to getting router information into state for our application.  Be patient on
this, it seems like there is no reason for this but there is a big payoff for this coming (besides the
time-traveling.)
 

Create a Ship Detail Component


Now that we have the router info stored in state, it’s time to build a component that will use it
and get our big payoff that’s been promised.

Page 32 of 37
To create the ship detail component, run this command:

This created a component with the store injected into the constructor nicely
It also defined it in the starships module
I’ll add this HTML code:

And the component TypeScript:

Page 33 of 37
This is all there is to the code!  It works for any ship that is selected from the list of ships.  The
magic here is in the fromStore.getCurrentShip selector.  Let’s take a closer look at that.
 

The Starship Selectors


Before looking at the getCurrentShip selector, I have to explain the other one I created:  the
getAllShipsWithId selector.

The first arg in the createSelector function is the “getAllShips” selector – it returns all of the
starships in the store
The second arg “allShips” will take the ships passed in from “getAllShips” and use a regular
expression to grab the starship id from the url property on the starship
This is necessary so that it will be easy to find a starship by its id later

Until now, selectors have been pretty boring, but here you can see what else you can do with
them
Here is the getCurrentShip selector and our payoff with the router information:

Page 34 of 37
Notes:
Note that this works because the list of ships we get from the Star Wars API has the details in
it, so there is no need for another API call
If your code needs to get more detailed info, you can of course do that in an
effect
The first arg of the createSelector function is the “getAllShipsWithId” selector – so we can
easily match the id with the id in the router info
The second arg is the fromRoot.getRouterInfo selector which gives us the router info
The third arg takes both of these and finds the ship by id using the routerInfo.params.shipId
Note that when the shipId changes, this also changes our selector and the
component updates!
So for example, you could have a previous/next set of buttons
that allowed you to navigate up and down the list w/o going
back to the grid, this code would execute whenever the route
was navigated to
For this shipId parm to make sense, let’s look at the Starships routing
module:

:shipId is added to our params object in the RouterStateUrl interface

And we just need a link in our list of starships:

Page 35 of 37
Results
Let’s take a look at how the site looks now.  First, the list of starships has changed to add the id
(I guess you wouldn’t have to show the id) and a link in the name of the starship:

If I click on the Millennium Falcon, here is our detail page:


URL=/ships/10/detail

Page 36 of 37
Time Traveling
Finally, here is a look at the Redux DevTools after clicking the “stopwatch icon” on the bottom
row of buttons:

Notice the ROUTER_NAVIGATION entries – those are added there (partly) so we can travel
back in time to see the state at a given point, along with actual navigation happening on the
page!

Conclusion
Let’s recap:
1. Router information is now stored in state – the single source of truth now for our url,
parameters and query parameters
2. The parameters can now easily be accessed inside our selectors (or anywhere else for that
matter)
3. Our component now doesn’t have to have code that gets the id and then retrieves the ship,
it is all handled in the selector
4. We can do time-traveling using Redux DevTools now
5. We have some very clean code
It is my wish that you will take the information you’ve learned in these NgRx tutorials and use
them on your job effectively.  Happy coding!

Page 37 of 37

You might also like