Managing side effects with @ngrx/effects
In this exercise you will create an effect for loading flights.
-
Open your
flight-booking.actions.tsfile and add aflightsLoadaction creator:Show code
[...] export const flightsLoad = createAction( '[FlightBooking] Flights load', props<{from: string, to: string, urgent: boolean}>() ); -
Open the file
flight-booking.effects.tsand add an effect that takes aflightsLoadaction, loads the requested flights and returns aflightsLoadedaction.Show code
import * as FlightBookingActions from './flight-booking.actions'; @Injectable() export class FlightBookingEffects { loadFlights$ = createEffect(() => this.actions$.pipe( ofType(FlightBookingActions.flightsLoad), switchMap(a => this.flightService.find(a.from, a.to, a.urgent)), map(flights => FlightBookingActions.flightsLoaded({flights})))); constructor( private actions$: Actions, private flightService: FlightService) {} }Tip: Import the
Actionstype from the module@ngrx/effects:import {Actions} from '@ngrx/effects'; -
Open the file
flight-search.component.ts. Change thesearchmethod so that it just dispatches aflightsLoadaction.Show code
search(): void { if (!this.from || !this.to) return; // New: this.store.dispatch(flightsLoad({ from: this.from, to: this.to, urgent: this.urgent })); // Old: /* this.flightService .find(this.from, this.to, this.urgent) .subscribe({ next: flights => { this.store.dispatch(new flightsLoaded({flights})); }, error: error => { console.error('error', error); } }); */ } -
Test the application.
-
Use the
Redux DevToolsChrome plugin to find out which actions are dispatched.
Bonus: Error Handling
- Open your
flight-booking.actions.tsfile and add anflightsLoadedErroraction:
export const flightsLoadedError = createAction(
'[FlightBooking] Flights loaded error',
props<{ error: any }>()
);
-
In your
flight-booking.effects.ts, add an error handler to the switchMap. This error handler should return theflightsLoadedErroraction.Show code
loadFlights$ = createEffect(() => this.actions$.pipe( ofType(FlightBookingActions.flightsLoad), switchMap(a => this.flightService.find(a.from, a.to, a.urgent).pipe( map(flights => FlightBookingActions.flightsLoaded({flights})), catchError(err => of(FlightBookingActions.flightsLoadedError({ error: err }))) )), )); -
Test your solution. You can simulate an error with the Browser's dev tools by activating offline module in the
Networktab. -
Use the Redux Dev Tools to make sure, that the
flightsLoadedErroraction is send to the store.