מדריך Angular – ניהול State מתקדם עם NgRx

מדריך Angular – ניהול State מתקדם עם NgRx

במאמר הקודם למדנו על מנגנון 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! הישארו איתנו.

שתפו את הפוסט

דילוג לתוכן