Перейти к содержанию

Reducers

NgRx Reducers являются чистыми функциями и отвечают за смену состояния хранилища в Angular приложении в ответ на возникновение действия, при этом каждый редюсер может изменять только определенную часть состояния.

Изменить состояние в NgRx можно ТОЛЬКО с использованием редюсеров.

users.actions.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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, поэтому очень важно определить значение части хранилища по умолчанию, которое задаст необходимую структуру и, если это необходимо, исходные значения свойств этой структуры.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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.

1
2
3
@NgModule({
  imports: [StoreModule.forRoot({users: usersReducer})],
})

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

Комментарии