概要
状態管理(state management)は「どこに変数を置くか?」という表層的な話ではない。
それは**“責務ごとに状態を分離し、変更の伝播範囲を制御するための構造設計”**である。
JavaScriptにおけるアプリケーション開発では、状態を ローカルに閉じるか、グローバルで共有するか の判断が、保守性・可読性・テスト容易性すべてに関わってくる。
本稿では、状態の分類・責務の設計・スコープの最適化・グローバル/ローカルの切り分け判断基準を体系的に解説する。
1. 状態の分類と設計意図
種類 | 説明 | 例 |
---|---|---|
ローカル状態 | 単一コンポーネント内に閉じる状態 | フォーム入力値、表示/非表示など |
グローバル状態 | 複数箇所からアクセス・共有される必要のある状態 | ログイン情報、言語設定、テーマ設定など |
2. ローカル状態の構成(局所性と自律性)
function Component() {
const [value, setValue] = useState('');
return (
<input value={value} onChange={e => setValue(e.target.value)} />
);
}
- ✅ コンポーネント内部のみに関係する状態はローカルで閉じる
- ✅ 状態の更新が他に影響を与えないため可読性と保守性が高い
3. グローバル状態の設計(共有と集中管理)
const globalState = {
user: null,
theme: 'dark'
};
function login(user) {
globalState.user = user;
}
- ✅ 状態が複数箇所で読み書きされるならグローバルへ昇格
- ✅ 状態の**集中管理(Store)**が必要になることも多い
4. 状態分離の原則:アクセス可能性 ≠ 必要性
- ❌ 「どこからでもアクセスできるからグローバルにする」
→ ✅ 本当に“複数箇所から参照/更新”されているのかを見極める
5. グローバル状態の構造設計パターン
// オブジェクトベースの集中管理
const store = {
state: {
user: null,
token: null
},
setUser(user) {
this.state.user = user;
},
reset() {
this.state = { user: null, token: null };
}
};
- ✅ 直接参照を避け、アクセサ関数を通すことで変更制御が可能
- ✅ 状態の責務が明示され、テストもしやすい構造になる
設計判断フロー
① 状態は UI構成要素のみに関係しているか? → ローカル状態で閉じる
② 状態は複数コンポーネント間で共有されるか? → グローバル昇格
③ 状態の変化は、どこまで伝播させる必要があるか? → 最小スコープで設計
④ グローバル状態の責務が混在していないか? → ストア構造を分割
⑤ 状態アクセスが読み取り/書き込みの両方必要か? → setterを分離する
よくあるミスと対策
❌ 全ての状態をグローバルに定義し、変更が多発
→ ✅ 状態のアクセス範囲と責務を最小に絞る
❌ ローカル状態が無秩序に肥大化
→ ✅ 複雑な構造は reducer や composable に分割
❌ グローバル状態に直接アクセスしてバグ温床に
→ ✅ アクセサ・アクション関数を介した構造に統一
結語
状態管理とは「値を保存する」ためではない。
それは**“状態の変化と伝播を構造として制御し、責務と影響範囲を最適化するための設計戦略”**である。
- UIローカルで閉じるべきものは閉じ、汚染を防ぐ
- グローバル状態は厳密な責任範囲と更新ルールを定める
- 状態の流れをコードに記述することで、設計が明確になる
JavaScriptにおける状態管理とは、
“状態を構造的に位置づけ、再現性と予測性を最大化するための設計技術である。”