react-state-management について
React開発者向けに状態管理パターンの選択と適用方法を解説するガイドです。ローカル、グローバル、サーバー、URL、フォームの状態を区別し、現代的なライブラリの例と移行方法を示します。
主な機能
- 01ローカル・グローバル・サーバー状態のパターン
- 02Redux Toolkit、Zustand、Jotaiの選定
- 03React QueryとSWRのガイド
- 04楽観的更新のパターン
- 05旧式Reduxからの移行ガイド
活用シーン
- 01Reactアプリのストア選定
- 02キャッシュされたサーバーデータの管理
- 03状態関連の問題のデバッグ
- 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 });
},
},
});
コメント
Markdown 対応