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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Rainer Hahnekamp
July 20, 2022
Technology
130
1
Share
NgRx Component Store
Slides for my talk on NgRx Component Store
Rainer Hahnekamp
July 20, 2022
More Decks by Rainer Hahnekamp
See All by Rainer Hahnekamp
Vitest Highlights in Angular
rainerhahnekamp
0
260
From Hours to Minutes - An AI Case Study with Sheriff
rainerhahnekamp
0
25
RxJS, Signals, and Native Observables: Answering the Critical Questions
rainerhahnekamp
0
27
Zurück in den Browser – Das Comeback der Frontend-Tests
rainerhahnekamp
0
74
From Hours to Minutes: An AI Case Study with Sheriff
rainerhahnekamp
0
140
RxJS, Signals & Native Observables
rainerhahnekamp
0
130
The Road to Angular Today Milestones, Mistakes & Momentum
rainerhahnekamp
0
130
Next Generation Angular
rainerhahnekamp
0
50
2025-09-05_Hold_the_Line.pdf
rainerhahnekamp
0
250
Other Decks in Technology
See All in Technology
AWS DevOps Agent or Kiro の使いどころを考える_20260402
masakiokuda
0
120
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
11k
OCI技術資料 : 証明書サービス概要
ocise
1
7.1k
SaaSに宿る21g
kanyamaguc
2
180
Sansanの認証基盤を支えるアーキテクチャとその振り返り
sansantech
PRO
1
120
FastMCP OAuth Proxy with Cognito
hironobuiga
3
230
第26回FA設備技術勉強会 - Claude/Claude_codeでデータ分析 -
happysamurai294
0
200
40代からのアウトプット ― 経験は価値ある学びに変わる / 20260404 Naoki Takahashi
shift_evolve
PRO
2
440
互換性のある(らしい)DBへの移行など考えるにあたってたいへんざっくり
sejima
PRO
0
480
MIX AUDIO EN BROADCAST
ralpherick
0
140
自分をひらくと次のチャレンジの敷居が下がる
sudoakiy
3
1k
How to install a gem
indirect
0
2k
Featured
See All Featured
Speed Design
sergeychernyshev
33
1.6k
GitHub's CSS Performance
jonrohan
1032
470k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
170
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
New Earth Scene 8
popppiees
2
1.9k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
0
470
The Art of Programming - Codeland 2020
erikaheidi
57
14k
エンジニアに許された特別な時間の終わり
watany
106
240k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
WCS-LA-2024
lcolladotor
0
500
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
0
250
Become a Pro
speakerdeck
PRO
31
5.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