Week 08 · Day 06 — NgRx:Reducer、Selector 與 Store

學習目標

  • createReducer / on 處理 action
  • createSelector 讀取狀態
  • 在元件用 Store 的 dispatch / select

重點

Reducer(純函式變換狀態)

import { createReducer, on } from '@ngrx/store';

interface TodoState { todos: Todo[] }
const initialState: TodoState = { todos: [] };

export const todoReducer = createReducer(
  initialState,
  on(addTodo, (state, { todo }) => ({
    ...state,
    todos: [...state.todos, todo]
  })),
  on(removeTodo, (state, { id }) => ({
    ...state,
    todos: state.todos.filter(t => t.id !== id)
  }))
);
- 純函式:輸入 state + action → 新 state - 不修改原 state,用 spread 產生新版

Selector(選取狀態)

import { createSelector } from '@ngrx/store';

export interface AppState { todos: TodoState }

export const selectTodoState = (s: AppState) => s.todos;
export const selectTodos = createSelector(
  selectTodoState,
  (state: TodoState) => state.todos
);

在元件中使用 Store

@Component({ ... })
export class TodoComponent {
  todos$ = this.store.select(selectTodos);   // 訂閱

  constructor(private store: Store) {}

  addTodo(todo: Todo): void {
    this.store.dispatch(addTodo({ todo }));  // 發出 action
  }
}
<ul>
  <li *ngFor="let t of todos$ | async">{{ t.title }}</li>
</ul>

實作

  1. 建立 todo.reducer.ts(處理 add/remove)
  2. 建立 selectors 取得 todos
  3. 在元件用 store.dispatchstore.select

作業

  • createReducer + on 實作 reducer
  • createSelector 選取狀態
  • 元件用 store.dispatch / store.select 操作