NgRx Ducks | Динамически фасады

от автора

Усовершенствование опыта разработки

Общаясь с коллегами из разных компаний, я заметил, что очень многие команды обожают NgRx. Во время наших дискуссий меня не покидала мысль:
«Как было бы хорошо меньше сопровождать код, а больше следовать гайдам написания, чтобы облегчить последующее масштабирование».
Это побудило меня начать изучение различных методик рефакторинга Redux. Я смотрел видео, читал статьи и документы Redux. В конце-концов, я написал плагин для NgRx под названием NgRx Ducks

Цели

В основном ngrx-ducks создан для упрощения работы с NgRx.

  1. Упрощенная обработка экшенов с помощью Decorator API, который уменьшает объем кода, который необходимо написать, чтобы настроить как редюсер (Reducer), так и экшен креатор (Action creator). NgRx Ducks генерирует экшен-креаторы и функции редюсера автоматически.
  2. Меньше технического сопровождения, так как вам не нужно писать энумераторы (enums) или юнион-типы (union types).
  3. Более ясная логика приложения обеспечивается благодаря интуитивно понятному типизированному API, который вы можете использовать в качестве внедряемого сервиса (injectable Service), который настраивает взаимодействие с Хранилищем (Store) за вас.

Как оно работает?

Эта библиотека работает как дополнительный слой над NgRx. Она автоматически создает экшен креаторы и функции редюсера за вас. Кроме того, вы получаете сервис, который можно использовать в своих компонентах. Этот Сервис предоставляет строго типизированный API, позволяющий как диспатчить (dispatching) экшены, так и селектить (selecting) данные из Хранилища.
Библиотека NgRx Ducks не меняет существующее поведение NgRx. Она только управляет Observable Хранилища и методом dispatch.

Так как NgRx Ducks опирается только на dispatch и тот факт, что Хранилище предоставляет Observable, NgRx Ducks остается совместимым с NgRx, даже если в релизе есть критические изменения.

Установка

NgRx Ducks легко интегрируется с существующим проектом NgRx. Достаточно установить пакет npm, и все готово к работе.

npm install @co-it/ngrx-ducks # или yarn add @co-it/ngrx-ducks

Decorator API

Основная идея NgRx Ducks — объединить экшен-типы и логику мутаторов (также называемые редюсерами). Поэтому был добавлен декоратор @Ducksify, аннотирующий обычный класс.

import { Ducksify } from '@co-it/ngrx-ducks';  @Ducksify<number>({   initialState: 0 }) export class Counter {}

Декоратор позволяет указать initialState вашего состояния. Передача initialState позволяет NgRx Ducks позже автоматически сгенерировать функцию редюсера.
Теперь можно размещать логику мутаций прямо внутри класса. Больше нет необходимости писать switch-case-выражения. Вместо этого мы создаем маппинг между типом экшена и логикой мутации, используя декоратор Action.

import { Action, Ducksify } from '@co-it/ngrx-ducks';  @Ducksify<number>({ /* ... */ }) export class Counter {   @Action('[Counter] Increase by passed value')   increaseBy(state: number, payload: number): number {     return state + payload;   } }

NgRx Ducks мапит каждый Экшен с соответствующей логикой мутации. Duck содержит всю необходимую информацию для генерации функции редюсера.

Функция редюсера

Функции редюсера автоматически генерируются с помощью NgRx Ducks. Фабрика reducerFrom создает справочную таблицу, чтобы сопоставить каждый экшен-тип с соответствующей логикой мутации.

import {    reducerFrom,   DucksifiedAction,   ... } from '@co-it/ngrx-ducks';  export function reducer(   state: number,    action: DucksifiedAction): number {    return reducerFrom(Counter)(state, action); }

Вам все еще нужно оборачивать reducerFrom внутри экспортируемой функции для корректной работы с компилятором AoT.
Сгенерированный редюсер необходимо добавить в ActionReducerMap с помощью NgRx (см. пример ниже).

Утиная сила!

Самое интересное еще впереди! Цель NgRx Ducks — упростить взаимодействие с Хранилищем. С автоматической генерацией функции редюсера все нормально, и поэтому давайте взглянем на динамический фасад, который также здесь создается.

Декоратор @Ducksify также заботится о регистрации вашей "утки" в качестве Сервиса в IoC-контейнере Angular. Это означает, что вы можете внедрять "утку" в свой компонент!

Диспатчинг экшенов в Хранилище

NgRx Ducks добавляет некоторые исправления в Duck, которые позволяют вам использовать простые вызовы функций вместо диспатчинга экшенов вручную. Вы получаете типизированный API внутри ваших компонентов.

import { Duck } from '@co-it/ngrx-ducks';  @Component({ /* ... */ }) export class CounterComponent {   constructor(@Inject(Counter) private _counter: Duck<Counter>) {     this.counter.incrementBy(42);   } }

Вы внедряете Duck, а не сам Counter. Duck автоматически создает экшен креатор для incrementBy, который диспатчит экшен с переданным значением (payload). Благодаря динамическим типам TypeScript вы сразу получаете автозаполнение в IDE.

Короче говоря, NgRx Ducks автоматизирует весь процесс обработки Экшенов. Вы настраиваете экшен один раз в Duck, а после этого — просто используете типизированный, динамический фасад, сгенерированный и обновленный автоматически за вас.

Выборка данных из Хранилища

Duck использует селекторы NgRx для чтения данных из Хранилища. У каждой "утки" есть хелпер (helper) pick, который принимает селектор.
Давайте представим, что наш Counter зарегистрирован как функция NgRx с ключом "counter". Это позволило бы нам следующую настройку селектора.

import { createFeatureSelector, createSelector} from '@ngrx/store';  const visitCounter = createFeatureSelector<number>('counter'); const count = createFeatureSelector<number>(count => count);  @Component({ /* ... */ }) export class CounterComponent {   count$: Observable<number>;constructor(@Inject(Counter) private _counter: Duck<Counter>) {      this.count$ = this.counter.pick(count);   this.counter.incrementBy(42);   } }

Вы можете посмотреть демо на stackblitz.io.

Duck позволяет осуществлять как триггеринг мутаций состояния, так и запрос данных из Хранилища. Вам нужен только один «утилизированный» Сервис, который настраивает удобный API для взаимодействия с Хранилищем.

И наконец

NgRx Ducks также легко интегрируется с Эффектами! НО мы это разберем подробно только в следующей статье.
Если же вам не терпится узнать об этом прямо сейчас, можете обратиться к комплексному примеру, который также доступен в stackblitz.io.

TL;DR

  • NgRx Ducks работает как дополнительный слой поверх NgRx.
  • Вы можете легко интегрировать NgRx Ducks в существующие проекты.
  • Duck
    …. автоматически генерирует экшен креаторы и функции редюсера
    .… делает ненужными энумераторы экшенов и юнион-типы
    …. это динамический фасад, который может быть внедрен в компонент
    .… обеспечивает динамически-типизированные само-диспатчные (self-dispatching; sorry) экшены
    …. позволяет читать данные из Хранилища с помощью pick-API
    .… может использоваться Эффектами (см. Демо)

Вот и все, ребята!

Надеюсь, мне удалось убедить вас попробовать NgRx Ducks. Кроме того, мне интересно, что вы думаете об этой библиотеке. Если у вас есть какие-то идеи, — достаточно написать на GitHub

ссылка на оригинал статьи https://habr.com/ru/post/485080/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *