Reducers¶
NgRx Reducers являются чистыми функциями и отвечают за смену состояния хранилища в Angular приложении в ответ на возникновение действия, при этом каждый редюсер может изменять только определенную часть состояния.
Изменить состояние в NgRx можно ТОЛЬКО с использованием редюсеров.
users.actions.ts
import { Action } from '@ngrx/store'
export enum UsersActions {
LoadUsers = '[Users Page] LoadUsers',
DeleteUsers = '[Users Page] DeleteUsers',
}
export interface User {
id: number
name: string
email: string
}
export class LoadUsers implements Action {
readonly type = UsersActions.LoadUsers
constructor(public payload: { users: User[] }) {}
}
export class DeleteUsers implements Action {
readonly type = UsersActions.DeleteUsers
}
export type UsersUnion = LoadUsers | DeleteUsers
users.reducer.ts
import {
UsersUnion,
UserActions,
} from '../actions/users.actions'
export interface State {
users: User[]
count: number
}
const initialState: State = {
users: [],
count: 0,
}
export function usersReducer(
state: State = initialState,
action: UsersUnion
) {
switch (action.type) {
case UsersActions.LoadUsers:
return {
...state,
users: action.payload.users,
}
case UsersActions.DeleteUsers:
return {
...state,
users: [],
}
default:
return state
}
}
Любое действие, отправляемое в хранилище методом dispatch()
, передается всем редюсерам, каждый из которых либо изменяет состояние согласно текущему действию, либо возвращает состояние нетронутым, если обработка такого действия в нем не предусмотрена.
Все изменения состояния хранилища происходят в Angular приложении синхронно, а их порядок зависит от порядка регистрации самих NgRx Reducers.
Редюсер принимает два аргумента:
- часть текущего состояния, за обработку которого он ответственен;
- обрабатываемое действие.
Поскольку все NgRx Reducers обрабатывают определенный набор действий и всегда должны возвращать состояние, здесь очень удобно применение оператора switch
.
При первом вызове редюсера в качестве значения состояния ему передается undefined
, поэтому очень важно определить значение части хранилища по умолчанию, которое задаст необходимую структуру и, если это необходимо, исходные значения свойств этой структуры.
export interface State {
users: User[]
count: number
}
const initialState: State = {
users: [],
count: 0,
}
export function usersReducer(
state: State = initialState,
action: UsersUnion
) {
/* ... */
}
Для содержания кода вашего Angular проекта в чистоте и во избежании путаницы, рекомендуется NgRx Reducers и обрабатываемые ими действия хранить в разных файлах. Подробно здесь.
В приложении регистрация NgRx Reducers осуществляется с помощью метода forRoot()
модуля StoreModule
.
@NgModule({
imports: [StoreModule.forRoot({users: usersReducer})],
})
Методу должен передаваться объект, ключами которого являются имена частей, формирующих глобальное хранилище, а их значениями - редюсеры, возвращающие значение этих частей хранилища.