Эта статья объясняет Создатель действий Функция, представленная в NGRX V7.4, и шаблон реализации с использованием ее. Создатель действий еще не был включен в ngrx.io Документация, но, пожалуйста, обратитесь к нему после того, как он будет добавлен в будущем.
Определение действия
Давайте рассмотрим, как написать NGRX до сих пор, внедряя простой счетчик. На этот раз счетчик определяет Приращение который получает и добавляет произвольное число и Сброс который сбрасывает счетчик как действия.
В предыдущем определении действия было обычным определением перевода типа действия, каждого класса действий, который имеет его, и тип объединения этого типа класса. Например, если вы определяете counter.actions.ts с действиями Приращение и Сброс , похоже, следующее. Приращение Увеличьте подсчет заданным числом и Сброс это действие, чтобы сбросить счет обратно в ноль.
// counter.actions.ts
import {Action} from '@ngrx/store';
export enum ActionTypes {
Increment = '[Counter] Increment',
Reset = '[Counter] Reset',
}
export class Increment implements Action {
readonly type = ActionTypes.Increment;
constructor (public payload: number) {}
}
export class Reset implements Action {
readonly type = ActionTypes.Reset;
}
export type ActionsUnion = Increment | Reset;
Этот файл переписан создателем действий следующим образом:
// counter.actions.ts
import {createAction, union} from '@ngrx/store';
export const increment = createAction(
'[Counter] Increment',
(payload: number) => ({payload})
);
export const reset = createAction(
'[Counter] Reset'
);
const actions = union({
increment,
reset,
});
export type ActionsUnion = typeof actions;
Функция CreateAction
Во -первых, мы обсудим CreateAction функция, которая заменяет определение класса. Эта функция возвращает Создатель действий Анкет Создатель действий – это функция, которая возвращает объект действия. Другими словами, действие отправки изменяется от экземпляра нового класса на возвращаемое значение функции.
import * as Actions from './actions'; // instance of action class store.dispatch(new Actions.Increment(1)); // Action Creator // function returns Action store.dispatch(Actions.increment(1));
Действие, которое принимает аргумент, передает функцию второму аргументу CreateAction функция Эта функция принимает аргумент и возвращает частичный объект действия. Это то же самое, что и определения поля конструктора и класса в традиционном классе действий.
Давайте посмотрим на Приращение действие снова. Второй аргумент – это функция, которая принимает числовое значение как полезная нагрузка Аргумент, а возвратное значение – это объект с полезная нагрузка имущество. Возвратное значение этой функции объединяется с объектом действия, созданного с первым аргументом, и, наконец, объектом действия {type: '[counter] Increment', Pielylate} будет создан.
// Create an action const action = Actions.increment(1); // action object has `type` console.log(action.type); // => '[Counter] Increment' // The object returned by the second argument is merged console.log(action.payload); // => 1
Кстати, actiontypes enum больше не нужна. Вы можете узнать больше об этом в более позднем разделе Reducer.
функция союза
ActionUnion Тип, который является составной частью ряда типов действий, требуется в нескольких местах, таких как редуктор и эффект. Обычный класс действий может обрабатывать тип типа союза типа класса как есть, но в случае функции необходимо объединить тип возврата функции. Это Ngrx союз функция, чтобы помочь этому.
Передайте всех создателей действий в Союз функционируйте и объявите его возвращаемое значение ** без экспорта **. Причина, по которой вы не хотите экспортировать, заключается в том, что вы хотите только этот тип. В том месте, где он был экспортирован и предоставлен внешне. Как только вы объявили Действия переменная, используйте тип экспортировать свой тип как Союз Анкет
// do not export return value
const actions = union({
increment,
reset,
});
// export only type
export type ActionsUnion = typeof actions;
Создайте Reducer
После определения создателя действий давайте сделаем Reducer соответствовать. При первоначальном использовании класса действий и перечисления это был следующий редуктор. Тип действия, переданный в аргумент, имеет тип ActionUnion , который описывает оператор переключения, который сравнивает action.type с переходом строки ActionTypes Анкет
import {ActionsUnion, ActionTypes} from './actions';
import {State, initialState} from './state';
export function reducer (state = initialState, action: ActionsUnion): State {
switch (action.type) {
case ActionTypes.Increment: {
return {
... state,
count: state.count + action.payload,
};
}
case ActionTypes.Reset: {
return {
... state,
count: 0,
};
}
default: {
return state;
}
}
}
Ниже приведен результат отражения предыдущего изменения определения действия в этом редукторе. Только оператор дела изменился. Тип действия, указанный в операторе дела, был изменен на Тип собственность, обладающая создателем действий. Таким образом, поскольку его можно получить непосредственно от создателя действий, нет необходимости отделяться в Enum на стороне определения действия.
import {ActionsUnion, increment, reset} from './actions';
import {State, initialState} from './state';
export function reducer (state = initialState, action: ActionsUnion): State {
switch (action.type) {
case increment.type: {
return {
... state,
count: state.count + action.payload,
};
}
case reset.type: {
return {
... state,
count: 0,
};
}
default: {
return state;
}
}
}
Создать эффекты
Используйте эффекты NGRX, чтобы определить побочный эффект вывода журнала каждый раз, когда добавляется счетчик и сброс. Традиционное определение действия следующее:
import {Injectable} from '@angular/core';
import {Effect, Actions, ofType} from '@ngrx/effects';
import {tap} from 'rxjs/operators';
import {ActionsUnion, ActionTypes} from './actions';
@Injectable()
export class CounterEffects {
constructor (private actions$: Actions) {}
@Effect({dispatch: false})
logger$ = this.actions$.pipe(
ofType(ActionTypes.Increment, ActionTypes.Reset),
tap(action => {
console.log(action);
}),
)
}
Как и в случае REDUCER, это только влияет на часть типа действия.
import { Injectable } from '@angular/core';
import { Effect, Actions, ofType } from '@ngrx/effects';
import { tap } from 'rxjs/operators';
import { ActionsUnion, increment, reset } from './actions';
@Injectable()
export class CounterEffects {
constructor(private actions$: Actions) { }
@Effect({ dispatch: false })
logger$ = this.actions$.pipe(
ofType(increment.type, reset.type),
tap(action => {
console.log(action);
}),
)
}
Отправка действий
Последняя часть – отправить действие. В традиционных классах действий экземпляры класса создаются и отправляются следующим образом.
import * as CounterActions from './state/counter/actions';
@Component({
selector: 'my-app',
template: `
{{ count$ | async }}
`,
})
export class AppComponent {
count$ = this.store.pipe(
select(state => state.counter.count),
);
constructor(private store: Store) { }
incrementOne() {
this.store.dispatch(new CounterActions.Increment(1));
}
reset() {
this.store.dispatch(new CounterActions.Reset());
}
}
Это изменяется, чтобы отправить возвратное значение, которое называется функцией создателя действий, как описано выше.
import * as CounterActions from './state/counter/actions';
@Component({
selector: 'my-app',
template: `
{{ count$ | async }}
`,
})
export class AppComponent {
count$ = this.store.pipe(
select(state => state.counter.count),
);
constructor(private store: Store) { }
incrementOne() {
this.store.dispatch(CounterActions.increment(1));
}
reset() {
this.store.dispatch(CounterActions.reset());
}
}
Это завершает все замены.
Преимущества создателя действий
Действия, определенные в классе, были неудобными в том, что они не смогли получить доступ Тип до тех пор, пока он не был создан, и большое количество кода, которое должно было быть написано формально.
В Создателе действий вы можете писать функции как функции, поэтому расточительный код значительно уменьшается. И функции и тестируемость такие же, как и раньше, без особых недостатков.
После того, как вы обновили NGRX вашего проекта до V7.4, в основном вы должны продолжить замену его создателем действий.
Резюме
-
CreateActionФункция была введена для создания создателя действий, который определяет действие как функцию вместо класса - Actiontype enum больше не нужен
- Влияние на восстановитель, эффекты и сторона отправки очень незначительны
Проверьте, как на самом деле работает счетчик -приложение, описанное в этой статье.
Оригинал: “https://dev.to/lacolaco/angular-how-to-use-action-creator-introduced-in-ngrx-v7-4-35d4”