במאמר הקודם למדנו על מנגנון Change Detection באנגולר, כעת נמשיך לנושא מורכב נוסף והוא עבודה עם NgRx לניהול State באפליקציית אנגולר.
במאמר זה, נסקור את ניהול ה-State באפליקציות אנגולר באמצעות NgRx, ספרייה לניהול מצב באנגולר המבוססת על Redux. NgRx מאפשרת לנו לנהל את מצב האפליקציה בצורה יעילה ומאורגנת, ומספקת כלים להנדסת תוכנה בצורה פרקטית ומתודולוגית.
מבוא ל-NgRx
NgRx היא ספרייה לניהול מצב באפליקציות אנגולר. היא מבוססת על Redux ומספקת כלים לניהול מצב בצורה עקבית וניתנת לתחזוקה. NgRx מבוססת על עקרונות ה-Flux ומאפשרת ניהול State באמצעות פעולות (Actions), חנויות (Stores), ומפחיתים (Reducers).
התקנת NgRx
כדי להשתמש ב-NgRx באפליקציית אנגולר, נתחיל בהתקנת החבילה. נשתמש בפקודה הבאה להתקנת NgRx:
npm install @ngrx/store @ngrx/effects
יצירת Store
השלב הראשון בניהול מצב עם NgRx הוא יצירת Store, שמכיל את כל הנתונים של האפליקציה. נתחיל בהגדרת State ראשוני ומפחית (Reducer) שמעדכן את ה-State:
import { Action, createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from './counter.actions';
export const initialState = 0;
const _counterReducer = createReducer(
initialState,
on(increment, (state) => state + 1),
on(decrement, (state) => state - 1),
on(reset, (state) => 0)
);
export function counterReducer(state, action) {
return _counterReducer(state, action);
}
הגדרת Actions
Actions הם אירועים שמתרחשים באפליקציה ומפעילים שינויים ב-State. ניצור כמה פעולות (Actions) בסיסיות עבור ספירה:
import { createAction } from '@ngrx/store';
export const increment = createAction('[Counter Component] Increment');
export const decrement = createAction('[Counter Component] Decrement');
export const reset = createAction('[Counter Component] Reset');
הוספת Store לאפליקציה
כדי להשתמש ב-Store באפליקציה, נוסיף את ההגדרות הדרושות למודול הראשי:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './counter.reducer';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
StoreModule.forRoot({ count: counterReducer }),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
שימוש ב-Store בקומפוננטה
כדי להשתמש ב-Store בקומפוננטה, נתחבר ל-Store ונפעיל פעולות:
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { increment, decrement, reset } from './counter.actions';
@Component({
selector: 'app-counter',
templateUrl: './counter.component.html',
})
export class CounterComponent {
count$: Observable<number>;
constructor(private store: Store<{ count: number }>) {
this.count$ = store.select('count');
}
increment() {
this.store.dispatch(increment());
}
decrement() {
this.store.dispatch(decrement());
}
reset() {
this.store.dispatch(reset());
}
}
שימוש ב-Effects לניהול תופעות צד
Effects מאפשרים לנו לנהל תופעות צד באפליקציה, כגון בקשות HTTP או פעולות אחרות שאינן משנות ישירות את ה-State. נשתמש ב-Effects כדי להוסיף ספירה לאחר ביצוע פעולה מסוימת:
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { map } from 'rxjs/operators';
import { increment, decrement } from './counter.actions';
@Injectable()
export class CounterEffects {
increment$ = createEffect(() =>
this.actions$.pipe(
ofType(increment),
map(() => decrement())
)
);
constructor(private actions$: Actions) {}
}
הוספת Effects לאפליקציה
כדי להשתמש ב-Effects באפליקציה, נוסיף את ההגדרות הדרושות למודול הראשי:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { counterReducer } from './counter.reducer';
import { CounterEffects } from './counter.effects';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
StoreModule.forRoot({ count: counterReducer }),
EffectsModule.forRoot([CounterEffects]),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
שימוש ב-Selectors לגישה ל-Store
Selectors מאפשרים לנו לגשת ל-State בצורה נוחה ומרכזית. ניצור Selector לגישה לספירה:
import { createSelector, createFeatureSelector } from '@ngrx/store';
export const selectCountState = createFeatureSelector<number>('count');
export const selectCount = createSelector(
selectCountState,
(state: number) => state
);
שימוש ב-Selectors בקומפוננטה
נשתמש ב-Selector בקומפוננטה כדי לגשת ל-State:
import { Component } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { Observable } from 'rxjs';
import { selectCount } from './counter.selectors';
import { increment, decrement, reset } from './counter.actions';
@Component({
selector: 'app-counter',
templateUrl: './counter.component.html',
})
export class CounterComponent {
count$: Observable<number>;
constructor(private store: Store) {
this.count$ = store.pipe(select(selectCount));
}
increment() {
this.store.dispatch(increment());
}
decrement() {
this.store.dispatch(decrement());
}
reset() {
this.store.dispatch(reset());
}
}
סיכום
במאמר זה, למדנו כיצד להשתמש ב-NgRx לניהול מצב באפליקציות אנגולר. סקרנו את העקרונות הבסיסיים של NgRx, התקנו והגדרנו Store, Actions, Reducers, Effects ו-Selectors. NgRx מאפשרת לנו לנהל את מצב האפליקציה בצורה מתודולוגית ומאורגנת, ולהקל על תחזוקת הקוד.
אם אתם מעוניינים ללמוד בצורה מעמיקה יותר אתם מוזמנים להתייעץ איתנו על קורס אנגולר.
במאמר הבא נלמד על RxJs! הישארו איתנו.