Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
120
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
From Hours to Minutes - An AI Case Study with Sheriff
rainerhahnekamp
0
8
RxJS, Signals, and Native Observables: Answering the Critical Questions
rainerhahnekamp
0
8
Zurück in den Browser – Das Comeback der Frontend-Tests
rainerhahnekamp
0
35
From Hours to Minutes: An AI Case Study with Sheriff
rainerhahnekamp
0
41
RxJS, Signals & Native Observables
rainerhahnekamp
0
61
The Road to Angular Today Milestones, Mistakes & Momentum
rainerhahnekamp
0
65
Next Generation Angular
rainerhahnekamp
0
31
2025-09-05_Hold_the_Line.pdf
rainerhahnekamp
0
170
Test Fest | Angular Unit Tests Distilled
rainerhahnekamp
0
440
Other Decks in Technology
See All in Technology
「Managed Instances」と「durable functions」で広がるAWS Lambdaのユースケース
lamaglama39
0
320
エンジニアとPMのドメイン知識の溝をなくす、 AIネイティブな開発プロセス
applism118
4
1.3k
LLM-Readyなデータ基盤を高速に構築するためのアジャイルデータモデリングの実例
kashira
0
250
IAMユーザーゼロの運用は果たして可能なのか
yama3133
1
280
Edge AI Performance on Zephyr Pico vs. Pico 2
iotengineer22
0
150
re:Invent2025 コンテナ系アップデート振り返り(+CloudWatchログのアップデート紹介)
masukawa
0
360
第4回 「メタデータ通り」 リアル開催
datayokocho
0
130
意外とあった SQL Server 関連アップデート + Database Savings Plans
stknohg
PRO
0
320
SREには開発組織全体で向き合う
koh_naga
0
250
年間40件以上の登壇を続けて見えた「本当の発信力」/ 20251213 Masaki Okuda
shift_evolve
PRO
1
130
会社紹介資料 / Sansan Company Profile
sansan33
PRO
11
390k
AI 駆動開発勉強会 フロントエンド支部 #1 w/あずもば
1ftseabass
PRO
0
360
Featured
See All Featured
Practical Orchestrator
shlominoach
190
11k
Making the Leap to Tech Lead
cromwellryan
135
9.7k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
RailsConf 2023
tenderlove
30
1.3k
GitHub's CSS Performance
jonrohan
1032
470k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
100
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.2k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3k
Code Reviewing Like a Champion
maltzj
527
40k
How to Ace a Technical Interview
jacobian
280
24k
Optimizing for Happiness
mojombo
379
70k
BBQ
matthewcrist
89
9.9k
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