BACK
Уроки44. scan как reducer
Уроки · 44

44. scan как reducer

Reducer pattern

Вместо «чистых» чисел можно использовать actions — объекты, описывающие, что произошло. Это базовая идея Redux/NgRx, и она прекрасно ложится на scan.

actions$.pipe(scan(reducer, initialState))
// reducer(state, action) → newState

Глоссарий

  • Action — объект, обычно с полем type, описывающий событие.
  • Reducer — чистая функция (state, action) => newState.
  • State — текущий «слепок» данных приложения.

Аналогия с NgRx

NgRx устроен по той же схеме: actions через диспатч → reducer → новое состояние → подписчики. Этот урок — компактная учебная версия большого паттерна.

Что нужно сделать

  1. Внутри reducer проверяйте action.type:
  2. 'increment'return { count: state.count + 1 }
  3. 'decrement'return { count: state.count - 1 }
  4. Иначе верните state без изменений.
  5. Важно: не мутируйте state — возвращайте новый объект.
  6. Ожидаемый вывод: Count: 1 → Count: 2 → Count: 1.
Решение spoiler · click to reveal
const { from, scan } = Rx;

const actions$ = from([
  { type: 'increment' },
  { type: 'increment' },
  { type: 'decrement' },
]);

const state$ = actions$.pipe(
  scan((state, action) => {
    if (action.type === 'increment') {
      return { count: state.count + 1 };
    }

    if (action.type === 'decrement') {
      return { count: state.count - 1 };
    }

    return state;
  }, { count: 0 })
);

state$.subscribe(state => console.log('Count: ' + state.count));
script.ts // TypeScript
CONSOLE · Console Output
Нажмите на запуск, чтобы увидеть результат...