Шаблоны, которые сделают вашу реализацию NgRx чище и понятнее

NgRx - отличная реализация Redux для Angular. Если вы уже реализовали это в проекте, вы, вероятно, заметили, что ваши классы эффектов были слишком большими, у вас было слишком много селекторов, и следить за тем, какой компонент отправляет действие, было не так просто, как должно было быть.

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

Эти идеи были реализованы в двух масштабных проектах и ​​пользовались большой популярностью у наших разработчиков.

Модуль государственной службы

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

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

Начнем с создания службы состояния приложения. AppStateService - это корневое состояние, также известное как общее состояние, которое содержит действия и селекторы, относящиеся ко всему приложению.

Затем мы создадим государственную службу для конкретного модуля. Компоненты внутри этого модуля не должны знать о Магазине и взаимодействовать с ним только с помощью этой службы.

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

Объединение выборок

Это простой и блестящий фрагмент кода, написанный Офиром Бушинским (אופיר בושינסקי):

Теперь у вас есть единый select метод для всех свойств состояния (с intellisense, не беспокойтесь…)

this.product$ = this.productStateService.select('product');

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

Класс очищающих эффектов

Вот распространенный метод воздействия:

Обычно у вас будет много методов, подобных этому, и скоро ваш класс Effects будет содержать 300 строк кода.

Чтобы сделать этот класс более читабельным, я предлагаю выделить реализацию в отдельную, максимально чистую функцию. Я бы также создал для этих функций отдельный файл (обычно называю его effects.ts)

Теперь мы добавим простую вспомогательную функцию:

А наш класс эффектов можно преобразовать в:

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

Оператор распространения

Оператор Spread (`…`) может использоваться вместо `Object.assign` для создания более чистого кода в редукторах.

return { …state, loading: true }

Подробнее об этом операторе здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals

Более чистая обработка ошибок

Если вы хотите иметь возможность обрабатывать все ошибки с помощью одного и того же обработчика (т.е. регистрировать их), вы можете создать класс с именем ErrorAction, который реализует Action. Затем каждое созданное вами действие при ошибке расширяет его:

Затем перехватите ErrorAction и делайте с ним все, что хотите.

На этом пока все. Я очень надеюсь, что это поможет вам навести порядок в том, что иногда может быть хаосом.

Я хотел бы еще раз поблагодарить Офира за его огромную помощь.

Если у вас есть какие-либо вопросы, комментарии или идеи, не стесняйтесь обращаться ко мне в разделе комментариев или в Twitter (@ TzachOvadia)