20. Create effect
In this section we will discuss NgRx's effects library a RxJS powered side effect model for @ngrx/store.
@ngrx/effects provides an API to model event sources as actions. Effects:
Listen for actions dispatched from @ngrx/store.
Isolate side effects from components, allowing for more pure components that select state and dispatch actions.
Provide new sources of actions to reduce state based on external interactions such as network requests, web socket messages and time-based events.
1. npm install @ngrx/effects
Execute the following command to install the effects library.
2. Dispatch new LoadAttendees action from the EventComponent
Before we can use effect we need to dispatch some actions from our EventComponent for our effects to listen to. We will not need the service in our component when we finish but for now we still need it to add Attendees.
Dispatch actions to
LoadAttendees
.Use the new
EventState
to limit the auto completion of what we are meant to be able to access from the store. Note we can still access everything as the store is a global object.Remove getAttendees method which will now be handled by the effect we are about to write.
3. Create an effect
Effects are all about listening for actions doing work and dispatching new actions. So in our example we will listen for the LoadAttendees
action do the work of getting them via a service and then dispatch a LoadAttendeesSuccess
action.
NgRx effects are a deep dive into observables and if you have not done a lot with RxJS or reactive streams in other languages can take some time to step through.
Create and attendees.effects.ts file in our state/attendees folder path.
Inject the
actions
observable from NgRx that will emit each action dispatched in our application and theEventService
to get the attendees.Add an
@Effect
decorator on top of a variable name of the effect.List the injected actions and filter on them with the
ofType
operator from NgRx.Use the
switchMap
operator to switch from the actions stream to a new observable returned from our EventService and return anLoadAttendeesSuccess
action.Add a
catchError
operator and return an observable ofLoadAttendeesFail
with a payload of the error.
4. Update reducer to listen for success and fail actions
Add an error property to the State object to hold any errors.
Update the attendee reducer to update the store with the attendees array form the affect.
Add a case for the LoadAttendeesFail action and set its payload to the error property of the state object.
5. Add effects array to index.ts file for EventModule
Our index.ts file in our event state folder is our public API so we want to add our different feature states effect to.
Re-export effects from the index.ts.
6. Register the feature effects in the EventModule
Register the effects with the
EffectsModule.forFeature
method.
7. Add default EffectsModule registration to root AppModule
For us to use effects in our app and reducers we need to have a root reducer and effect to start with. The root reducer could just be an object and the effects an empty array but we need to have them. The feature effects and reducers we make are then added to them as we lazily load them.
Add forRoot with an empty array for the AppModule.
Even before we write selectors we can see our app should working using our new effects.
8. Create a getAttendees selector
Similar to making selectors for our spinner we will now make them for our attendees reducer. You will end up having a selectors file for each reducer and they can become very logic heavy and need unit test but for now ours are quite simple.
Create selector for selecting attendees.
9. Use selector in EventComponent
Use getAttendees selector.
RxJS Operators and higher order observables
It is important to know which higher order observables to use with your effects to avoid race conditions. A higher order observable is just a fancy name for an observable that emits observable like the ones below.
Operator
When to use
switchMap
Cancels the current subscription/request and can cause race condition
Use for get requests or cancelable requests like searches
concatMap
Runs subscriptions/requests in order and is less performant
Use for get, post and put requests when order is important
mergeMap
Runs subscriptions/requests in parallel
Use for put, post and delete methods when order is not important
exhaustMap
Ignores all subsequent subscriptions/requests until it completes
Use for login when you do not want more requests until the initial one is complete
StackBlitz Link
Extras and Homework
These extra sections are for doing after the course or if you finish a section early. Please move onto the next section if doing this as a workshop when the instructor advises.
WARNING: Some of these extra sections will make it more difficult to copy and paste the code examples later on in the course.
You might need to apply the code snippet examples a little more carefully amongst any "extras section" code you may add. If you are up for some extra challenges these sections are for you.
Try out the @ngrx/schematics to scaffold out an application.
Schematics are Angular's way of being able to have custom code generators. You can read more here https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2
You will be wondering why we did not do this from the start and save us a lot of typing? Well first you need to know what you are doing before you can use the scaffolding tools as many students get lost in all the code it makes versus building it up from from nothing for the first time.
Steps:
Run this command to install the schematics
npm i @ngrx/schematics -D
Run this command to set them as the default schematics
ng config cli.defaultCollection @ngrx/schematics
Run this command to make a default empty root store.
ng g store State --root --statePath state --module app.module.ts
Run this command to make a container component
ng generate container Event2 --state reducers/index.ts --stateInterface Event2
Run this command to make the new feature module
ng g module party ng g c party/containers/party --module party/party.module.ts
Run this command to make the NgRx feature parts like reducer and effects etc
ng generate feature party/party --flat false
Last updated