Как правильно использовать ngRx?

Использование ngRx является одним из популярных подходов к управлению состоянием в приложениях на основе Angular. ngRx реализует паттерн управления состоянием Flux, который помогает упорядочить и структурировать код приложения, особенно если оно имеет сложную логику и большое количество данных.

Вот ряд шагов, которые вам следует выполнить, чтобы правильно использовать ngRx в вашем приложении:

1. Установка: Первым делом вам необходимо установить необходимые npm-пакеты. Это можно сделать следующей командой в консоли:

npm install @ngrx/store @ngrx/effects --save

2. Создание действий (actions): В ngRx основные изменения в состоянии происходят путем отправки действий. Действия представляют собой объекты, которые описывают то, что происходит в вашем приложении. Вы можете создавать действия с помощью классов или просто использовать константы. Например:

import { createAction, props } from '@ngrx/store';

export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');

export const setCount = createAction(
  '[Counter] Set Count',
  props<{ count: number }>()
);

3. Создание редукторов (reducers): Редукторы – это чистые функции, которые обрабатывают действия и возвращают новое состояние. Редукторы должны быть чистыми функциями, то есть они не должны иметь побочных эффектов и должны всегда возвращать новое состояние, а не изменять исходное. Например:

import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from './counter.actions';

export const initialState = 0;

export const counterReducer = createReducer(
  initialState,
  on(increment, state => state + 1),
  on(decrement, state => state - 1),
  on(reset, state => 0)
);

4. Создание эффектов (effects): Эффекты используются для обработки асинхронных действий или побочных эффектов, таких как вызов API. Эффекты могут слушать действия, запускать побочные эффекты и диспатчить новые действия. Например:

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { map, mergeMap } from 'rxjs/operators';
import { ApiService } from './api.service';
import { loadItems, itemsLoaded } from './item.actions';

@Injectable()
export class ItemEffects {
  loadItems$ = createEffect(() =>
    this.actions$.pipe(
      ofType(loadItems),
      mergeMap(() => this.apiService.getItems()),
      map(items => itemsLoaded({ items }))
    )
  );

  constructor(
    private actions$: Actions,
    private apiService: ApiService
  ) {}
}

5. Подключение к хранилищу (store): Хранилище (store) является централизованным хранилищем состояния вашего приложения. Вы можете подключить редукторы и эффекты к хранилищу в модуле вашего приложения. Например:

import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { counterReducer } from './counter.reducer';
import { ItemEffects } from './item.effects';

@NgModule({
  imports: [
    StoreModule.forRoot({ count: counterReducer }),
    EffectsModule.forRoot([ItemEffects])
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

6. Диспатчинг действий и выборка состояния: Теперь вы можете диспатчить действия из компонентов и выбирать состояние из хранилища с помощью селекторов. Например:

import { Component } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { increment, decrement, reset } from './counter.actions';

@Component({
  selector: 'app-counter',
  template: `
    <button (click)="increment()">Increment</button>
    <div>Current Count: {{ count$ | async }}</div>
    <button (click)="decrement()">Decrement</button>
    <button (click)="reset()">Reset Counter</button>
  `
})
export class CounterComponent {
  count$ = this.store.pipe(select('count'));

  constructor(private store: Store<{ count: number }>) {}

  increment() {
    this.store.dispatch(increment());
  }

  decrement() {
    this.store.dispatch(decrement());
  }

  reset() {
    this.store.dispatch(reset());
  }
}

Вот некоторые основные шаги, которые вам следует выполнить при использовании ngRx в вашем приложении Angular. Однако, это только базовый обзор, и есть много других возможностей и концепций, которые можно использовать с ngRx для улучшения структуры и производительности вашего приложения. Рекомендуется изучать документацию и руководства ngRx для получения более полной информации и практического опыта работы с этой библиотекой.