2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおける状態管理設計:ローカル vs グローバル、再レンダリング最小化、ステートの正規化戦略

Posted at

概要

状態管理とは「値を保存する」ことではない。
それは**「UIとデータを最小コストで同期させ続ける構造設計」**である。

状態が肥大化すればロジックは壊れ、
共有しすぎればコンポーネントは鈍重になり、
非正規化された構造はバグの温床となる。

本稿では、以下の観点からモダンJavaScriptアプリケーションにおける状態管理設計戦略を提示する:

  • ローカル vs グローバルの責務定義
  • 再レンダリング最小化の構造
  • ステートの正規化と派生設計
  • 非同期状態と一貫性の保証
  • 永続化・ストレージとの橋渡し

1. ローカル vs グローバル状態の原則

✅ ローカル状態(UIスコープ)

  • ボタンの押下状態
  • モーダルの開閉
  • 現在のページ番号
const [isOpen, setIsOpen] = useState(false);

✅ グローバル状態(アプリ全体に影響)

  • ログインユーザー情報
  • カート内容
  • アプリ設定
import { userStore } from '@/stores/user';

→ ✅ **「誰が管理し、誰が使うか」**で切り分けるのが本質


2. ステート正規化:配列をマップで持つ構造

// ❌ 非正規化
const users = [
  { id: 'u01', name: 'Toto' },
  { id: 'u02', name: 'Mir' },
];

// ✅ 正規化
const userById = {
  u01: { id: 'u01', name: 'Toto' },
  u02: { id: 'u02', name: 'Mir' },
};
const userIds = ['u01', 'u02'];
  • ✅ 再取得・更新がO(1)
  • ✅ 重複を回避し、一貫性を保てる
  • ✅ Redux Toolkitなどの正規化支援ライブラリも有効

3. 派生状態(Derived State)の戦略

const totalPrice = cartItems.reduce((sum, item) => sum + item.price, 0);
  • ✅ 派生値は状態に含めない
  • 関数で導出することで信頼性を担保
  • ✅ memo化・selector設計が重要(Recoil, Zustand など)

4. 再レンダリングを最小化する構造

// ❌ すべての状態を1つにまとめると全部が再描画
const [state, setState] = useState({ a, b, c });

// ✅ 状態を粒度ごとに分割
const [count, setCount] = useState(0);
const [input, setInput] = useState('');
  • 粒度を分けることでパフォーマンスが安定
  • ✅ グローバルステートでも購読単位を最小に

5. 状態と永続化ストレージの接続設計

useEffect(() => {
  const stored = localStorage.getItem('theme');
  if (stored) setTheme(stored);
}, []);
  • ✅ ステートとストレージを直接結ばず、Adapterを設計
  • ✅ JSON.parse / stringify の一元化
  • ✅ SSR対応時はhydrationタイミングの制御が必要

設計判断フロー

① この状態はどこで必要? → ローカル/グローバル切り分け

② 同一データを複数場所で参照していないか? → 正規化へ

③ 状態に「結果」ではなく「原因」を保存しているか? → 派生は関数に分離

④ 状態が肥大化していないか? → 粒度分割 + 再レンダリング最適化

⑤ ストレージと直結していないか? → Adapter or hook経由に構造化

よくあるミスと対策

❌ すべての状態をグローバルに持たせてUIが鈍重化

→ ✅ **“必要なところにだけ届ける”**という設計の逆算を行う


❌ データの冗長表現が複数存在し、片方だけ更新されバグに

→ ✅ 正規化 + セレクターによる導出に切り替える


❌ 状態が深くネストされて操作が難解に

→ ✅ 構造をフラットに、参照・更新の経路を明示的に


結語

状態管理とは「データを保管する」ことではない。
それはUIの整合性とアプリ全体の一貫性を保証する、構造の中核設計である。

  • スコープで役割を分け
  • 粒度で責任を分離し
  • 計算と保存を区別する

JavaScriptにおける状態管理設計とは、
“壊れず、重くならず、説明可能な構造をつくる”ための戦略である。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?