Side Effects with NGRX Effects
In this exercise you will create an effect for loading flights.
Creating an Effect
-
Open your
flight-booking.actions.ts
file and add aloadFlights
action creator:Show code
[...] export const loadFlights = createAction( '[FlightBooking] LoadFlights', props<{from: string, to: string, urgent: boolean}>() );
-
Open the file
flight-booking.effects.ts
and add an effect that takes aFlightsLoadAction
, loads the requested flights and returns aFlightsLoadedAction
.Show code
@Injectable() export class FlightBookingEffects { loadFlights$ = createEffect(() => this.actions$.pipe( ofType(loadFlights), switchMap(a => this.flightService.find(a.from, a.to, a.urgent)), map(flights => flightsLoaded({ flights })) ) ); constructor(private actions$: Actions, private flightService: FlightService) {} }
Tipp: Import the
Actions
type from the module@ngrx/effects
:import {Actions} from '@ngrx/effects';
-
Open the file
flight-search.component.ts
. Change thesearch
method so that it just dispatches aloadFlights
action.Show code
search(): void { if (!this.from || !this.to) return; // New: this.store.dispatch(loadFlights({ from: this.from, to: this.to, urgent: this.urgent })); // Old: /* this.flightService .find(this.from, this.to, this.urgent) .subscribe( flights => { this.store.dispatch(new flightsLoaded({flights})); }, error => { console.error('error', error); } ); */ }
-
Test the application.
-
Use the
Redux DevTools
Chrome plugin to find out which actions are dispatched.
Bonus: Error Handling
- Open your
flight-booking.actions.ts
file and add an LoadFlightsError Action without a payload:
export const loadFlightsError = createAction('[FlightBooking] Load Flights Error');
-
In your
flight-booking.effects.ts
, add an error handler to the switchMap. This error handler should return theloadFlightError
action.Show code
loadFlightBookings$ = createEffect(() => this.actions$.pipe( ofType(loadFlights), switchMap((a) => this.flightService.find(a.from, a.to, a.urgent).pipe( map((flights) => flightsLoaded({ flights })), catchError((err) => of(loadFlightsError())) ) ) ) );
-
Test your solution. You can simulate an error with the Browser's dev tools by activating offline module in the
Network
tab. -
Use the Redux Dev Tools to make sure, that the
loadFlightsError
action is send to the store.