NgRx Effects are used to handle side effects in your Angular application, such as making API calls, persisting data, logging, navigation, or analytics. They listen for specific actions, perform some (often asynchronous) work, and then dispatch new actions with the results.
This keeps your reducers pure and focused only on updating state, while effects take care of talking to the outside world.
login, loginSuccess, loginFailure that describe what happened.createEffect: Helper function to define an effect.Actions stream: Injectable stream of all dispatched actions.ofType: Filters the actions stream by action type.mergeMap, switchMap, concatMap, catchError are used to handle async workflows.The typical structure of an NgRx effect looks like this:
// Generic pattern for an NgRx effect
effectName$ = createEffect(() =>
this.actions$.pipe(
ofType(someAction),
mergeMap(action =>
this.someService.doSomething(action.payload).pipe(
map(result => someActionSuccess({ result })),
catchError(error => of(someActionFailure({ error })))
)
)
)
);
Important points about this pattern:
createEffect wraps your observable and tells NgRx it is an effect.this.actions$ is a stream of every action dispatched in the app.ofType(someAction) filters only the actions you care about.
// auth.effects.ts - effect that handles the login API call
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { AuthService } from '../auth.service';
import { login, loginSuccess, loginFailure } from './auth.actions';
import { map, mergeMap, catchError } from 'rxjs/operators';
import { of } from 'rxjs';
@Injectable()
export class AuthEffects {
constructor(private actions$: Actions, private authService: AuthService) {}
login$ = createEffect(() =>
this.actions$.pipe(
ofType(login),
mergeMap(action =>
this.authService.login(action.credentials).pipe(
map(user => loginSuccess({ user })),
catchError(error => of(loginFailure({ error })))
)
)
)
);
}
login action is dispatched from a component with user credentials.login$ effect listens for login using ofType(login).AuthService.login() to perform the actual HTTP request.loginSuccess action containing the user data.loginFailure action.login({ credentials }).login$ effect receives the action from the Actions stream.authService.login(credentials) (HTTP request to backend).loginSuccess({ user }) is dispatched and reducers update the auth state.loginFailure({ error }) is dispatched and you can show an error message.Notice that reducers never perform the HTTP call. They simply react to loginSuccess and loginFailure actions to update state.
mergeMap for concurrent requests, switchMap to cancel previous requests, and concatMap to queue them.catchError and dispatch a clear failure action.$ suffix by convention (e.g., login$).login$ effect (like above) that calls an API and dispatches loginSuccess/loginFailure actions.initApp$ effect that loads initial data when an AppInit action is dispatched.mergeMap, switchMap, and concatMap in an effect that loads a list of items. Observe how they behave when multiple load actions are dispatched quickly.loginSuccess using Angular Router.