• システム開発に関わる内容をざっくりと書いていく

Context API / Zustand キャッチアップ

Context API / Zustand:アプリ全体で状態を共有する方法

Reactアプリが少しずつ大きくなってくると、「この値、どの画面でも使いたい」「ログインユーザーを全画面で保持したい」みたいなニーズが出てくる。
そのとき使うのがグローバル状態管理

Reactにはいくつか方法があるけど、今回は実務でよく出てくるContext APIと、使いやすくて軽量なZustandを紹介する。


Context APIとは?

Reactに標準で備わってる「どこからでも状態を読み書きできる仕組み」。
小〜中規模アプリならこれで十分。

構成イメージ:

tsx
// 1. Contextを作成
const UserContext = createContext<UserContextType | undefined>(undefined);

// 2. Providerで囲む
<UserContext.Provider value={{ username, login, logout }}>
{children}
</UserContext.Provider>

// 3. useContextで中身を読む
const { username } = useContext(UserContext);

よくある使い道

  • ログインユーザー情報
  • ロケール(言語設定)
  • テーマ(ライト/ダーク)

カスタムフックに切り出すと便利

tsx
export const useUser = () => {
const context = useContext(UserContext);
if (!context) throw new Error("UserProviderが必要です");
return context;
};

→ 毎回useContext(UserContext)って書かなくてよくなる


メリット・デメリット

メリットデメリット
標準機能で導入コストなし値が変わると全てのコンポーネントが再レンダリングされる
TypeScriptで型安全に設計できるグローバルにしたくないものまで広がりやすい
カスタムフック化で簡潔にネストが深くなるとProvider地獄になることも

Zustandとは?

「もっと手軽に」「シンプルに」「効率よく」状態を共有したいときに使える軽量ライブラリ。
Reduxほど重くなく、Contextより効率がいい。

bash
npm install zustand

基本構成

tsx
// store.ts
import { create } from 'zustand';

type Store = {
username: string;
login: (name: string) => void;
logout: () => void;
};

export const useUserStore = create<Store>((set) => ({
username: '',
login: (name) => set({ username: name }),
logout: () => set({ username: '' }),
}));

使う側

tsx
const { username, login } = useUserStore();

Zustandのメリット

  • Provider不要(どこでも使える)
  • 分割再レンダリング対応(必要な部分だけ再描画)
  • シンプルなAPIで導入が楽

ContextとZustandの使い分け

シーンおすすめ
小〜中規模、標準で済ませたいContext API
状態が多い、大規模、効率重視Zustand
Providerが多すぎてつらいZustand
状態のセレクター管理がしたいZustand

状態管理設計のコツ

  • Propsバケツリレー問題:子→孫→ひ孫へpropsを渡すのが面倒 → グローバル管理で解決
  • 責務の切り分け:UIの状態(開閉など)はlocal、ユーザー情報などはglobal
  • 型定義をしっかり:ContextもZustandもTypeScriptで型定義しておくと後がラク

👇 サンプル:Context APIで認証状態を管理するアプリ


👇 サンプル:Zustandで認証状態を管理するアプリ

まとめ

  • Context APIはReact標準のグローバル状態管理
  • ZustandはProviderなし・再レンダリング効率◎の軽量な代替手段
  • 状態の性質(UI局所 or アプリ全体)によってローカルとグローバルを使い分ける
  • グローバル状態が整理されていると、複数ページ構成でもコードが散らかりにくい