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
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
Angular Architecture Revisited Modernizing Angular Architectural Patterns
rainerhahnekamp
0
30
NgRx SignalStore: The Power of Extensibility
rainerhahnekamp
0
330
Vitest Highlights in Angular
rainerhahnekamp
0
290
From Hours to Minutes - An AI Case Study with Sheriff
rainerhahnekamp
0
35
RxJS, Signals, and Native Observables: Answering the Critical Questions
rainerhahnekamp
0
31
Zurück in den Browser – Das Comeback der Frontend-Tests
rainerhahnekamp
0
83
From Hours to Minutes: An AI Case Study with Sheriff
rainerhahnekamp
0
150
RxJS, Signals & Native Observables
rainerhahnekamp
0
150
The Road to Angular Today Milestones, Mistakes & Momentum
rainerhahnekamp
0
140
Other Decks in Technology
See All in Technology
EBS暗号化に失敗してEC2が動かなくなった話
hamaguchimmm
2
200
マルチプロダクトの信頼性を効率良く保っていくために
kworkdev
PRO
0
160
弁護士ドットコム株式会社 エンジニア職向け 会社紹介資料
bengo4com
1
150
ARIA Notifyについて
ryokatsuse
1
120
LLM時代の検索アーキテクチャと技術的意思決定
shibuiwilliam
3
1.2k
AWS DevOps Agentはチームメイトになれるのか?/ Can AWS DevOps Agent become a teammate
kinunori
6
740
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.4k
Chasing Real-Time Observability for CRuby
whitegreen
0
120
Keeping Ruby Running on Cygwin
fd0
0
160
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
16k
AzureのIaC管理からログ調査まで、随所に役立つSkillsとCustom-Instructions / Boosting IaC and Log Analysis with Skills
aeonpeople
0
230
AWS Agent Registry の基礎・概要を理解する/aws-agent-registry-intro
ren8k
3
380
Featured
See All Featured
Scaling GitHub
holman
464
140k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
250
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
520
How to Think Like a Performance Engineer
csswizardry
28
2.6k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
480
The World Runs on Bad Software
bkeepers
PRO
72
12k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9k
So, you think you're a good person
axbom
PRO
2
2k
Art, The Web, and Tiny UX
lynnandtonic
304
21k
sira's awesome portfolio website redesign presentation
elsirapls
0
220
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
340
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
110
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