Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
NgRx Component Store
Search
Rainer Hahnekamp
July 20, 2022
Technology
1
130
NgRx Component Store
Slides for my talk on NgRx Component Store
Rainer Hahnekamp
July 20, 2022
Tweet
Share
More Decks by Rainer Hahnekamp
See All by Rainer Hahnekamp
Vitest Highlights in Angular
rainerhahnekamp
0
190
From Hours to Minutes - An AI Case Study with Sheriff
rainerhahnekamp
0
20
RxJS, Signals, and Native Observables: Answering the Critical Questions
rainerhahnekamp
0
22
Zurück in den Browser – Das Comeback der Frontend-Tests
rainerhahnekamp
0
55
From Hours to Minutes: An AI Case Study with Sheriff
rainerhahnekamp
0
94
RxJS, Signals & Native Observables
rainerhahnekamp
0
110
The Road to Angular Today Milestones, Mistakes & Momentum
rainerhahnekamp
0
110
Next Generation Angular
rainerhahnekamp
0
43
2025-09-05_Hold_the_Line.pdf
rainerhahnekamp
0
220
Other Decks in Technology
See All in Technology
ブログの作成に音声AIツールを使って音声入力しようとした話
smt7174
1
150
React 19時代のコンポーネント設計ベストプラクティス
uhyo
17
6.7k
AITuberKit+Bedrock AgentCoreで作る 3Dキャラクターエージェント
yokomachi
2
1.5k
既存のログ監視システムをクラウドっぽく実装してみた
tjmtrhs
0
190
バイブコーディングで作ったものを紹介
tatsuya1970
0
170
Oracle Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
4
1.5k
APMの世界から見るOpenTelemetryのTraceの世界 / OpenTelemetry in the Java
soudai
PRO
0
130
Agent Ready になるためにデータ基盤チームが今年やること / How We're Making Our Data Platform Agent-Ready
zaimy
0
150
なぜAIは チーム開発を 速くしないのか
tan_go238
8
3.3k
チーム開発の基礎_研究を事業につなげるために
cyberagentdevelopers
PRO
8
4.2k
技術選定 したい人 したくない人
shirayanagiryuji
0
320
三菱UFJ銀行におけるエンタープライズAI駆動開発のリアル / Enterprise AI_Driven Development at MUFG Bank: The Real Story
muit
5
9k
Featured
See All Featured
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
1
140
The Cost Of JavaScript in 2023
addyosmani
55
9.7k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.7k
What does AI have to do with Human Rights?
axbom
PRO
0
2k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
What's in a price? How to price your products and services
michaelherold
247
13k
Being A Developer After 40
akosma
91
590k
We Have a Design System, Now What?
morganepeng
55
8k
The Curious Case for Waylosing
cassininazir
0
250
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.8k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.3k
Transcript
NgRx Component Store NgRx Component Store Rainer Hahnekamp 20.7.2022
About Me... • Rainer Hahnekamp ANGULARarchitects.io • Trainings and Consulting
@RainerHahnekamp Professional NgRx https://www.ng-news.com https://www.youtube.com /c/RainerHahnekamp
Agenda • NgRx Family • Theory • Selectors • Actions
• Effects • Miscellaneous
NgRx Family Store Effects Entity Data Router Store Store Devtools
Schematics ESLint Plugin Component Store Component
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
Use cases • Complicated, local state logic • Multiple instances
of same components • Different static logic (Decoupling, Shared) • ~Simplified, global state
API ComponentStore SideEffects Read Write select(): Observable patchState() setState() updater()
// like reducer effect()
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: [] }); } }
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), })) ); }
Using the ComponentStore @Component({ templateUrl: './holidays.component.html', standalone: true, imports: [...],
providers: [HolidaysStore], }) export class HolidaysComponent { holidays$ = this.holidaysStore.holidays$; constructor(private holidaysStore: HolidaysStore) { } }
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), })); } }
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); } }
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 }); }
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); } }
Comparison to store • Same reactive behaviour • No devtools
• Scalability issues • Simpler • Nice goodies ◦ patchState ◦ Debounced selectors
Also keep in mind • Disposing of resources is built-in
• Combination with @ngrx/store possible • Can also manage global state ◦ via {providedIn: 'root'}
When to use? • Instead of services based on BehaviorSubject
• Non-global state • Early phases of application development
Alternatives Elf @rx-angular/state
Summary • Simple State Management • Reactive Behaviour • Easy
to upgrade to NgRx Store later
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