action_reducer_pattern.md (2422B)
1 # Action/Reducer Pattern 2 3 ## Redux-Like Action/Reducer Pattern 4 5 ``` 6 ┌──────────────────────────┐ 7 │ UI / View │ 8 │ (components, widgets) │ 9 └────────────┬─────────────┘ 10 │ 11 │ dispatch(action) 12 ▼ 13 ┌───────────────┐ 14 │ ACTION │ 15 │ type + data │ 16 └──────┬────────┘ 17 │ 18 │ sent to 19 ▼ 20 ┌──────────────────────────────────────┐ 21 │ STORE (currentState+ reducer) │ 22 └────────────┬─────────────────────────┘ 23 │ 24 │ calls 25 ▼ 26 ┌───────────────────────┐ 27 │ REDUCER │ 28 │ newState = f( │ 29 │ state, action │ 30 │ ) │ 31 └─────────┬─────────────┘ 32 │ 33 │ returns newState 34 ▼ 35 ┌───────────────┐ 36 │ STORE │ 37 │ updates state │ 38 └──────┬────────┘ 39 │ 40 │ notifies subscribers 41 ▼ 42 ┌───────────────────────────┐ 43 │ UI / View │ 44 │ re-renders from state │ 45 └───────────────────────────┘ 46 ``` 47 48 For more predictable updates, you can implement a Redux-style pattern using 49 typed discriminated unions: 50 51 ```ts 52 type Action = 53 | { type: "ADD_TODO"; payload: { text: string } } 54 | { type: "TOGGLE_TODO"; payload: { id: number } }; 55 56 function reducer(state: AppState, action: Action): AppState { 57 switch (action.type) { 58 case "ADD_TODO": 59 return { ...state, todos: [...state.todos, action.payload] }; 60 case "TOGGLE_TODO": 61 return { ...state /* ... */ }; 62 default: 63 return state; 64 } 65 } 66 ``` 67 68 TypeScript's exhaustive checking ensures your switch covers every action type, 69 preventing silent missed cases.