Frontend
October 15, 2023

Управление состоянием с NgRx в Angular

Управление состоянием - это когда ты отслеживаешь изменения данных в приложении и обновляешь интерфейс соответствующим образом.

Например, в соцсети у тебя есть лента постов. Когда кто-то добавляет новый пост, он появляется в ленте - так работает управление состоянием. Оно помогает, чтобы интерфейс приложения всегда соответствовал данным.

Зачем это нужно:

  • Приложение работает предсказуемо и правильно отображает данные.
  • Легче отлаживать, так как изменения локализованы в определенных местах кода.
  • Можно вернуться к предыдущему состоянию, например, отменить действие.

NgRx - библиотека для управления состоянием в Angular. Она помогает писать стабильные и предсказуемые приложения. NgRx используют Redux подход, он сейчас очень популярен.

Основные концепции NgRx

Actions

Actions - это простые объекты, которые описывают изменения в приложении. Например:

{
  type: 'addPost',
  payload: {
    title: 'Новый пост', 
    text: 'Текст поста'
  }
}

Это action добавляет новый пост. Он содержит type и данные в payload.

Reducers

Reducers - это функции, которые обновляют состояние на основе action.

Например, reducer для добавления поста:

function postsReducer(state, action) {

  switch (action.type) {
    
    case 'addPost':
    
      return [...state, action.payload];
      
    default:
    
      return state;
      
  }
  
}

Он возвращает новый массив постов со значением из action.

Store

Store - это объект, который хранит состояние всего приложения в одном месте.

Store использует reducers для обновления состояния при получении actions.

Это позволяет легко отслеживать изменения и делать Undo/Redo.

Пример использования NgRx

Давай создадим простое приложение для записи идей. Будет две кнопки:

  • Добавить идею
  • Удалить последнюю идею

И список идей.

Сначала импортируем нужные модули из NgRx:

import {StoreModule} from '@ngrx/store';
import {StoreDevtoolsModule} from '@ngrx/store-devtools';

Определим объект состояния в корневом компоненте:

export interface AppState {
  ideas: string[]; 
}

const initialState: AppState = {
  ideas: []
};

Создадим reducer для ideas:

export function ideasReducer(state, action) {

  switch (action.type) {
  
    case 'ADD_IDEA':
      return [...state, action.idea];
    
    case 'REMOVE_IDEA':
      return state.slice(0, -1);
      
    default:
      return state;
  }
  
}

В корневом модуле настроим Store с этим reducer:

StoreModule.forRoot({ideas: ideasReducer}, {initialState})

Теперь добавим компоненты:

<button (click)="addIdea()">Добавить идею</button>

<button (click)="removeIdea()">Удалить идею</button> 

<div *ngFor="let idea of ideas$ | async">{{idea}}</div>

В компонентах dispatcher actions и связываем state:

constructor(private store: Store<AppState>) {}

ideas$ = this.store.select(state => state.ideas);

addIdea() {
  this.store.dispatch({type: 'ADD_IDEA', idea: 'Новая идея!'}); 
}

removeIdea() {
  this.store.dispatch({type: 'REMOVE_IDEA'});
}

Вот и все! Теперь приложение корректно управляет состоянием.

Преимущества и рекомендации

Преимущества NgRx:

  • Предсказуемость - понятно, как меняется состояние.
  • Отладка - можно посмотреть историю изменений.
  • Тестирование - легко тестировать reducer и actions.
  • Масштабируемость - состояние не переплетается между компонентами.

Рекомендации:

  • Начни с малого - вводи постепенно в существующий проект.
  • Разделяй большой reducer на маленькие.
  • Используй библиотеки, как NgRx Entity для облегчения работы.
  • Добавь NgRx Devtools для удобной отладки.

Итог

Управление состоянием очень важно для стабильных приложений. NgRx - отличный инструмент для этого в Angular. Потренируйся на примерах, почитай документацию. Это поможет писать лучший код и делать крутые приложения!