Upgrade to Pro — share decks privately, control downloads, hide ads and more …

NgRx Component Store

NgRx Component Store

Slides for my talk on NgRx Component Store

Rainer Hahnekamp

July 20, 2022

Transcript

20 slides
  1. About Me... • Rainer Hahnekamp ANGULARarchitects.io • Trainings and Consulting

    @RainerHahnekamp Professional NgRx https://www.ng-news.com https://www.youtube.com /c/RainerHahnekamp
  2. NgRx Family Store Effects Entity Data Router Store Store Devtools

    Schematics ESLint Plugin Component Store Component
  3. Main facts • (Little) sibling to @ngrx/store • Local /

    component state management • State vanishes with component (by default) • Push-based • All logic included in single service
  4. Use cases • Complicated, local state logic • Multiple instances

    of same components • Different static logic (Decoupling, Shared) • ~Simplified, global state
  5. Defining the state export interface HolidaysState { holidays: Holiday[]; favouriteIds:

    number[]; } @Injectable() export class HolidaysStore extends ComponentStore<HolidaysState> { constructor(private httpClient: HttpClient, private config: Configuration) { super({ holidays: [], favouriteIds: [] }); } }
  6. Selectors export interface HolidaysState { holidays: Holiday[]; favouriteIds: number[]; }

    @Injectable() export class HolidaysStore extends ComponentStore<HolidaysState> { constructor(private httpClient: HttpClient, private config: Configuration) { super({ holidays: [], favouriteIds: [] }); } readonly holidays$ = this.select(({ holidays, favouriteIds }) => holidays.map((holiday) => ({ ...holiday, isFavourite: favouriteIds.includes(holiday.id), })) ); }
  7. Using the ComponentStore @Component({ templateUrl: './holidays.component.html', standalone: true, imports: [...],

    providers: [HolidaysStore], }) export class HolidaysComponent { holidays$ = this.holidaysStore.holidays$; constructor(private holidaysStore: HolidaysStore) { } }
  8. Actions @Injectable() export class HolidaysStore extends ComponentStore<HolidaysState> { // ...

    addFavourite(holidayId: number) { this.patchState((state) => ({ favouriteIds: [...state.favouriteIds, holidayId], })); } removeFavourite(holidayId: number) { this.patchState((state) => ({ favouriteIds: state.favouriteIds.filter((id) => id !== holidayId), })); } }
  9. Using the ComponentStore @Component({ templateUrl: './holidays.component.html', standalone: true, imports: [...],

    providers: [HolidaysStore], }) export class HolidaysComponent { holidays$ = this.holidaysStore.holidays$; constructor(private holidaysStore: HolidaysStore) { } addFavourite(id: number) { this.holidaysStore.addFavourite(id); } removeFavourite(id: number) { this.holidaysStore.removeFavourite(id); } }
  10. Effects @Injectable() export class HolidaysStore extends ComponentStore<HolidaysState> { // ...

    readonly load = this.effect((i$: Observable<void>) => { return i$.pipe( switchMap(() => this.httpClient.get<Holiday[]>(this.#baseUrl).pipe( tapResponse((holidays) => { const finalHolidays = holidays.map((holiday) => ({ ...holiday, imageUrl: `${this.config.baseUrl}${holiday.imageUrl}`, })); this.#setHolidays(finalHolidays); }, console.error) ) ) ); }); #setHolidays = (holidays: Holiday[]) => this.patchState({ holidays }); }
  11. Using the ComponentStore @Component({ templateUrl: './holidays.component.html', standalone: true, imports: [...],

    providers: [HolidaysStore], }) export class HolidaysComponent { holidays$ = this.holidaysStore.holidays$; constructor(private holidaysStore: HolidaysStore) { this.holidaysStore.load(); } addFavourite(id: number) { this.holidaysStore.addFavourite(id); } removeFavourite(id: number) { this.holidaysStore.removeFavourite(id); } }
  12. Comparison to store • Same reactive behaviour • No devtools

    • Scalability issues • Simpler • Nice goodies ◦ patchState ◦ Debounced selectors
  13. Also keep in mind • Disposing of resources is built-in

    • Combination with @ngrx/store possible • Can also manage global state ◦ via {providedIn: 'root'}
  14. When to use? • Instead of services based on BehaviorSubject

    • Non-global state • Early phases of application development
  15. Further Reading/Watching • Original Design Document ◦ https://hackmd.io/zLKrFIadTMS2T6zCYGyHew?view • Official

    Documentation ◦ https://ngrx.io/guide/component-store • Alex Okrushko on Component Store ◦ https://www.youtube.com/watch?v=v5WSUE1_YHM

More Decks by Rainer Hahnekamp

Other Decks in Technology