Упрощаем работу с NgRX Store с помощью фасадов

NgRX одновременно c решением массы проблем управления состоянием приложения, добавляет сложность и связанность между компонентами и менеджером состояния. Это может затруднить повторное использование компонентов в других проектах, если они напрямую зависят от конкретной реализации стора.

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

Структура стора

В большинстве проектов, использующих NgRx, структура стора стандартна и включает следующие элементы:

  • Эффекты (Effects): Отвечают за обработку побочных эффектов, таких как HTTP-запросы.

  • Стейт (State): Хранит текущее состояние приложения.

  • Селекторы (Selectors): Используются для получения данных из стейта.

  • Экшены (Actions): Определяют, какие изменения должны произойти в состоянии.

  • Редюсеры (Reducers): Обрабатывают экшены и обновляют стейт.

Компоненты приложения обращаются к этим элементам для получения и изменения состояния.

Проблема зависимости компонентов

No Facade

Компоненты напрямую взаимодействуют со стейтом, селекторами и экшенами, что может создавать тесную связанность между компонентами и стором. Это делает компоненты зависимыми от конкретной реализации стейта, что затрудняет их повторное использование или изменение в будущем.

Фасады как решение

Yes Facade

Фасады позволяют разграничить компоненты и стор, обеспечивая независимость компонентов от конкретного менеджера стейта.

Пример фасада

Рассмотрим пример фасада, который возвращает данные из бэк-энда:

import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { selectUserData, UserActions } from './store';

@Injectable({
  providedIn: 'root'
})
export class UserFacade {
  userData$: Observable<UserData> = this.store.select(selectUserData);

  constructor(private store: Store) {}

  loadUserData() {
    this.store.dispatch(UserActions.loadUserData());
  }
}

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

Преимущества фасадов

  1. Упрощение компонентов: Компоненты становятся легче и проще, так как они обращаются только к фасаду.

  2. Изолированность: Компоненты становятся независимыми от конкретной реализации стейта.

  3. Тестируемость: Фасады легче тестировать, так как они представляют собой простые классы, которые можно подменять моками.

Вывод

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