Week 08 · Day 03 — 簡單狀態管理:BehaviorSubject

學習目標

  • BehaviorSubject 管理共享狀態
  • .next() 更新狀態、.asObservable() 安全暴露
  • 元件訂閱取得最新狀態

重點

為什麼需要狀態管理 - 多個元件要共享資料(如登入狀態、待辦清單) - 保證資料「單一來源」(single source of truth)

StateService

import { BehaviorSubject, Observable } from 'rxjs';

interface AppState {
  user: User | null;
  todos: Todo[];
  loading: boolean;
}

@Injectable({ providedIn: 'root' })
export class StateService {
  private state: AppState = {
    user: null,
    todos: [],
    loading: false
  };

  private state$ = new BehaviorSubject(this.state);  // 初始值必填

  getState(): Observable<AppState> {
    return this.state$.asObservable();   // 外界只能讀,不能直接 next
  }

  setUser(user: User | null): void {
    this.state = { ...this.state, user };          // 不可變更新
    this.state$.next(this.state);
  }

  addTodo(todo: Todo): void {
    this.state = {
      ...this.state,
      todos: [...this.state.todos, todo]
    };
    this.state$.next(this.state);
  }
}

為什麼 BehaviorSubject - 需給初始值 - 訂閱者一訂閱就「立刻收到目前值」 - (相比 subject 只推之後的值)

用 spread 保持不可變 - 避免直接修改原物件,用 ... 生出新版後才指派

實作

  1. 建立 StateService,含 user / todos / loading
  2. 實作 setUser / addTodo
  3. 建立元件訂閱 getState() 觀察更新

作業

  • BehaviorSubject 建立共享狀態
  • .next() 更新,asObservable() 暴露
  • 用 spread 做到不可變更新