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
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
210
From Hours to Minutes - An AI Case Study with Sheriff
rainerhahnekamp
0
22
RxJS, Signals, and Native Observables: Answering the Critical Questions
rainerhahnekamp
0
23
Zurück in den Browser – Das Comeback der Frontend-Tests
rainerhahnekamp
0
62
From Hours to Minutes: An AI Case Study with Sheriff
rainerhahnekamp
0
110
RxJS, Signals & Native Observables
rainerhahnekamp
0
120
The Road to Angular Today Milestones, Mistakes & Momentum
rainerhahnekamp
0
110
Next Generation Angular
rainerhahnekamp
0
48
2025-09-05_Hold_the_Line.pdf
rainerhahnekamp
0
220
Other Decks in Technology
See All in Technology
Data Hubグループ 紹介資料
sansan33
PRO
0
2.8k
EMからICへ、二周目人材としてAI全振りのプロダクト開発で見つけた武器
yug1224
3
250
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
44k
Kaggleで鍛えたスキルの実務での活かし方 競技とプロダクト開発のリアル
recruitengineers
PRO
1
100
Introduction to Sansan for Engineers / エンジニア向け会社紹介
sansan33
PRO
6
72k
A Gentle Introduction to Transformers
keio_smilab
PRO
1
100
Digitization部 紹介資料
sansan33
PRO
1
7k
ヘルシーSRE
tk3fftk
2
230
【SLO】"多様な期待値" と向き合ってみた
z63d
2
290
Databricksアシスタントが自分で考えて動く時代に! エージェントモード体験もくもく会
taka_aki
0
310
マルチロールEMが実践する「組織のレジリエンス」を高めるための組織構造と人材配置戦略
coconala_engineer
2
370
ソフトウェアアーキテクトのための意思決定術: Create Decision Readiness—The Real Skill Behind Architectural Decision
snoozer05
PRO
29
8.8k
Featured
See All Featured
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.1k
エンジニアに許された特別な時間の終わり
watany
106
240k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
270
KATA
mclloyd
PRO
35
15k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
140
Building a Modern Day E-commerce SEO Strategy
aleyda
45
8.8k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
86
Documentation Writing (for coders)
carmenintech
77
5.3k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
290
Bash Introduction
62gerente
615
210k
Utilizing Notion as your number one productivity tool
mfonobong
4
240
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