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
Zurück in den Browser – Das Comeback der Frontend-Tests
rainerhahnekamp
0
20
From Hours to Minutes: An AI Case Study with Sheriff
rainerhahnekamp
0
28
RxJS, Signals & Native Observables
rainerhahnekamp
0
48
The Road to Angular Today Milestones, Mistakes & Momentum
rainerhahnekamp
0
56
Next Generation Angular
rainerhahnekamp
0
24
2025-09-05_Hold_the_Line.pdf
rainerhahnekamp
0
160
Test Fest | Angular Unit Tests Distilled
rainerhahnekamp
0
440
Micro Frontends: Necessity, Implementation, and Challenges
rainerhahnekamp
2
940
Software richtig testen - Ganz praktisch!
rainerhahnekamp
0
140
Other Decks in Technology
See All in Technology
生成AIシステムとAIエージェントに関する性能や安全性の評価
shibuiwilliam
2
280
AIで加速する次世代のBill Oneアーキテクチャ〜成長の先にある軌道修正〜
sansantech
PRO
1
150
不確実性に備える ABEMA の信頼性設計とオブザーバビリティ基盤
nagapad
5
9.4k
pmconf 2025 大阪「生成AI時代に未来を切り開くためのプロダクト戦略:圧倒的生産性を実現するためのプロダクトサイクロン」 / The Product Cyclone for Outstanding Productivity
yamamuteki
3
3k
経営から紐解くデータマネジメント
pacocat
8
1.7k
DGX SparkでローカルLLMをLangChainで動かした話
ruzia
1
150
useEffectってなんで非推奨みたいなこと言われてるの?
maguroalternative
3
1.8k
SRE視点で振り返るメルカリのアーキテクチャ変遷と普遍的な考え
foostan
2
3.1k
レガシーシステム刷新における TypeSpec スキーマ駆動開発のすゝめ
tsukuha
4
870
一億総業務改善を支える社内AIエージェント基盤の要諦
yukukotani
7
2.1k
履歴テーブル、今回はこう作りました 〜 Delegated Types編 〜 / How We Built Our History Table This Time — With Delegated Types
moznion
13
8.3k
ローカルLLM基礎知識 / local LLM basics 2025
kishida
25
11k
Featured
See All Featured
Music & Morning Musume
bryan
46
7k
4 Signs Your Business is Dying
shpigford
186
22k
Docker and Python
trallard
46
3.7k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.8k
Done Done
chrislema
186
16k
Writing Fast Ruby
sferik
630
62k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
360
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
Bash Introduction
62gerente
615
210k
KATA
mclloyd
PRO
32
15k
Side Projects
sachag
455
43k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
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