Selectors and Effects
Selectors
1import { createFeatureSelector, createSelector } from '@ngrx/store';
2
3// Feature selector
4export const selectSamuraiState = createFeatureSelector<SamuraiState>('samurai');
5
6// Basic selectors
7export const selectAllSamurai = createSelector(
8 selectSamuraiState,
9 state => state.samurai
10);
11
12export const selectLoading = createSelector(
13 selectSamuraiState,
14 state => state.loading
15);
16
17// Derived selectors
18export const selectSamuraiCount = createSelector(
19 selectAllSamurai,
20 samurai => samurai.length
21);
22
23export const selectSamuraiById = (id: number) => createSelector(
24 selectAllSamurai,
25 samurai => samurai.find(s => s.id === id)
26);
27
28// Parameterized selector
29export const selectSamuraiByClan = (clan: string) => createSelector(
30 selectAllSamurai,
31 samurai => samurai.filter(s => s.clan === clan)
32);
Effects (Side Effects)
1import { Injectable, inject } from '@angular/core';
2import { Actions, createEffect, ofType } from '@ngrx/effects';
3import { of } from 'rxjs';
4import { map, catchError, switchMap, exhaustMap } from 'rxjs/operators';
5
6@Injectable()
7export class SamuraiEffects {
8 private actions$ = inject(Actions);
9 private http = inject(HttpClient);
10
11 loadSamurai$ = createEffect(() =>
12 this.actions$.pipe(
13 ofType(loadSamurai),
14 switchMap(() =>
15 this.http.get<Samurai[]>('/api/samurai').pipe(
16 map(samurai => loadSamuraiSuccess({ samurai })),
17 catchError(error => of(loadSamuraiFailure({ error: error.message })))
18 )
19 )
20 )
21 );
22
23 addSamurai$ = createEffect(() =>
24 this.actions$.pipe(
25 ofType(addSamurai),
26 exhaustMap(({ samurai }) =>
27 this.http.post<Samurai>('/api/samurai', samurai).pipe(
28 map(saved => addSamuraiSuccess({ samurai: saved })),
29 catchError(error => of(addSamuraiFailure({ error: error.message })))
30 )
31 )
32 )
33 );
34}