mcpField
R
react-state-management

react-state-management

github.com/wshobson開発41.9k15.5k 回インストール2 週間前に更新
リポジトリ

react-state-management について

React開発者向けに状態管理パターンの選択と適用方法を解説するガイドです。ローカル、グローバル、サーバー、URL、フォームの状態を区別し、現代的なライブラリの例と移行方法を示します。

主な機能

  1. 01ローカル・グローバル・サーバー状態のパターン
  2. 02Redux Toolkit、Zustand、Jotaiの選定
  3. 03React QueryとSWRのガイド
  4. 04楽観的更新のパターン
  5. 05旧式Reduxからの移行ガイド

活用シーン

  1. 01Reactアプリのストア選定
  2. 02キャッシュされたサーバーデータの管理
  3. 03状態関連の問題のデバッグ
  4. 04旧式Reduxコードの移行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wshobson/agents --skill react-state-management

インストール後、Claude Code で/react-state-managementを入力して読み込まれたか確認します。

同梱ファイルreferences/details.md

詳細

React の状態管理

ローカルコンポーネントの状態からグローバルストア、サーバー状態の同期まで、モダンな React の状態管理パターンを包括的に解説します。

このスキルを使う場面

  • React アプリでグローバルな状態管理をセットアップするとき
  • Redux Toolkit、Zustand、Jotai のどれを選ぶか判断するとき
  • React Query や SWR でサーバー状態を管理するとき
  • 楽観的更新を実装するとき
  • 状態に関連する問題をデバッグするとき
  • レガシーな Redux からモダンなパターンへ移行するとき

中核となる概念

1. 状態のカテゴリ
種類説明ソリューション
ローカル状態コンポーネント固有の UI 状態useState、useReducer
グローバル状態コンポーネント間で共有Redux Toolkit、Zustand、Jotai
サーバー状態リモートデータ、キャッシュReact Query、SWR、RTK Query
URL 状態ルートパラメータ、検索React Router、nuqs
フォーム状態入力値、バリデーションReact Hook Form、Formik
2. 選択基準
Small app, simple state → Zustand or Jotai
Large app, complex state → Redux Toolkit
Heavy server interaction → React Query + light client state
Atomic/granular updates → Jotai

クイックスタート

Zustand(最もシンプル)
// store/useStore.ts
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'

interface AppState {
  user: User | null
  theme: 'light' | 'dark'
  setUser: (user: User | null) => void
  toggleTheme: () => void
}

export const useStore = create<AppState>()(
  devtools(
    persist(
      (set) => ({
        user: null,
        theme: 'light',
        setUser: (user) => set({ user }),
        toggleTheme: () => set((state) => ({
          theme: state.theme === 'light' ? 'dark' : 'light'
        })),
      }),
      { name: 'app-storage' }
    )
  )
)

// Usage in component
function Header() {
  const { user, theme, toggleTheme } = useStore()
  return (
    <header className={theme}>
      {user?.name}
      <button onClick={toggleTheme}>Toggle Theme</button>
    </header>
  )
}

詳細なパターンと実例

詳細なパターンのドキュメントは references/details.md にあります。上記のナビゲーション層で不十分な場合は、そのファイルを参照してください。

ベストプラクティス

すべきこと
  • 状態をコロケーションする - 状態は使われる場所のできるだけ近くに保ちます
  • セレクターを使う - 選択的な購読で不要な再レンダリングを防ぎます
  • データを正規化する - ネストした構造をフラットにして更新しやすくします
  • すべてに型を付ける - TypeScript で完全にカバーすることでランタイムエラーを防ぎます
  • 関心事を分離する - サーバー状態(React Query)とクライアント状態(Zustand)
すべきでないこと
  • 過度にグローバル化しない - すべてをグローバル状態に入れる必要はありません
  • サーバー状態を複製しない - React Query に管理させます
  • 直接ミューテーションしない - 常にイミュータブルな更新を使います
  • 派生データを保存しない - 代わりに計算します
  • パラダイムを混在させない - カテゴリごとに主要なソリューションを 1 つ選びます

移行ガイド

レガシーな Redux から RTK へ
// Before (legacy Redux)
const ADD_TODO = "ADD_TODO";
const addTodo = (text) => ({ type: ADD_TODO, payload: text });
function todosReducer(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [...state, { text: action.payload, completed: false }];
    default:
      return state;
  }
}

// After (Redux Toolkit)
const todosSlice = createSlice({
  name: "todos",
  initialState: [],
  reducers: {
    addTodo: (state, action: PayloadAction<string>) => {
      // Immer allows "mutations"
      state.push({ text: action.payload, completed: false });
    },
  },
});

コメント