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
140
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
170
NgRx SignalStore: The Power of Extensibility
rainerhahnekamp
0
350
Vitest Highlights in Angular
rainerhahnekamp
0
340
From Hours to Minutes - An AI Case Study with Sheriff
rainerhahnekamp
0
45
RxJS, Signals, and Native Observables: Answering the Critical Questions
rainerhahnekamp
0
37
Zurück in den Browser – Das Comeback der Frontend-Tests
rainerhahnekamp
0
100
From Hours to Minutes: An AI Case Study with Sheriff
rainerhahnekamp
0
180
RxJS, Signals & Native Observables
rainerhahnekamp
0
170
The Road to Angular Today Milestones, Mistakes & Momentum
rainerhahnekamp
0
170
Other Decks in Technology
See All in Technology
関西に縁あるMicrosoft MVPsが語るCopilotの未来
kasada
0
630
Databricks 月刊サービスアップデート 2026年05月号
tyosi1212
0
120
AI フレンドリーなエラー監視を TypeScript で実現する
shinyaigeek
2
190
Javaコミュニティをもっと楽しむための9箇条
takasyou
0
740
プラットフォームエンジニア ワークショップ/ platform-workshop
databricksjapan
0
140
オンコールの負荷軽減のためのBits Assistant 活用方法 / How to Use Bits Assistant to Reduce the Workload on On-Call Staff
sms_tech
1
350
AIガバナンス実践 - 生成AIコネクタのデータ漏洩リスクと実務対策
knishioka
0
140
権限管理設計を完全に理解した
rsugi
2
240
さきさん文庫の書籍ができるまで
sakiengineer
0
320
Kiro CLI v2.0.0がやってきた!
kentapapa
0
230
oracle-to-databricks-migration-with-llm-and-dbt
casek
1
380
OpenClawとHermesAgentでAI新入社員を作った話
takanoriyanada
0
150
Featured
See All Featured
Writing Fast Ruby
sferik
630
63k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
160
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
550
エンジニアに許された特別な時間の終わり
watany
107
240k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.3k
HDC tutorial
michielstock
2
680
The SEO identity crisis: Don't let AI make you average
varn
0
480
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
710
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
810
Un-Boring Meetings
codingconduct
0
300
Balancing Empowerment & Direction
lara
6
1.1k
Building Applications with DynamoDB
mza
96
7.1k
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