『状態機械』が複雑UIの事故を防ぐ
XStateは状態機械(Finite State Machine / Statechart)の概念をTypeScriptで実装するライブラリで、複雑なUI状態・業務ロジックを宣言的に書けます。「useStateが10個以上あって何が何だかわからない」「if文の組み合わせ爆発」「非同期処理が競合してデータ整合性が壊れる」といった典型的な事故を構造的に防げます。v5(2024)でTypeScript型推論が一段引き上がり、新規プロジェクトの選択肢として急速に普及しています。
採用すべき5つのシグナル
- useStateが5個以上あるコンポーネントが複数ある
- 非同期処理(fetch・mutation)の重複実行が発生
- ボタン連打・ダブルサブミット等の競合バグが頻発
- 業務ロジックの状態遷移をドキュメント化したい
- Reduxの複雑性に疲れた
主要機能
- States & Transitions: 状態とイベントを宣言的に記述
- Hierarchical States: 状態の階層化で複雑性管理
- Parallel States: 並行状態の表現
- Actors: 状態機械を組み合わせるアクターモデル
- Stately Studio: GUIで状態機械を視覚化・編集
- TypeScript型推論: 状態・イベントが完全型安全
Redux/Zustand/XState比較
Redux: 中央集権ストア・大規模アプリ向き・学習コスト高。
Zustand: 軽量・シンプル・型安全・小〜中規模向き。
XState: 状態遷移の宣言・複雑業務ロジック向き・学習コスト中。
使い分け: シンプルUI状態はZustand・複雑な業務遷移はXState。
実装パターン
(1) マシン定義: createMachine({ states: { idle: { on: { FETCH: 'loading' } }, loading: { invoke: { src: fetchUser, onDone: 'success' } } } })
(2) React統合: const [state, send] = useMachine(machine)
(3) イベント送信: send({ type: 'FETCH' })
(4) 状態判定: state.matches('loading')
(5) Actor連携: 複数マシンを組み合わせる
典型的なユースケース
- フォーム: 入力→バリデーション→送信→成功/失敗の状態遷移
- ウィザード: 多段階フォーム・進行状況管理
- 認証フロー: ログイン→OTP→2FA→セッション維持
- 決済フロー: カート→決済→確認→完了の状態管理
- WebSocket接続: 接続→再接続→切断の状態遷移
本番採用の判断基準
- 本番実績: Microsoft・Figma等での採用例
- 学習コスト: 中規模(1〜2週間)
- Reactとの統合: useMachineフックで自然
- Stately Studio: 視覚化で非エンジニアにも説明可能
- ベンダーロックイン: OSS・Stately Studioは別契約
実装で詰まる3つの落とし穴
- 状態の粒度: 細かすぎると保守困難・大きすぎると複雑度爆発
- Actor通信: 複数マシン連携の設計を誤ると依存関係地獄
- テスト: 状態遷移パターンの組み合わせテストが必要
30日学習プラン
- 1週目: XState基礎・シンプルな状態機械を書く
- 2週目: React統合・useMachine・Hierarchical States
- 3週目: Actorモデル・Parallel States・複雑ロジック
- 4週目: Stately Studio・本番統合・テスト戦略
関連リンク
Reactパフォーマンスは Reactパフォーマンス、状態管理全般は React状態管理、TanStack Queryとの組み合わせは TanStack Query深掘り を参照してください。