© TOOLS BOX — Next.js / React / TypeScript コードサンプル集

サンプルガイド
←サンプル一覧
reactstate-management

React Context で軽量なグローバル状態を管理する

useState + createContext + useContext を組み合わせてグローバルな状態を管理する最小パターン。Zustand などの外部ライブラリが不要なケースに適している。

難易度: 中級·更新: 2026-04-15

対応バージョン

react 19typescript 5

前提環境

React hooks(useState, useContext)の基本を理解していること

概要

createContext + useContext を使うことで props drilling を避けつつ、 軽量なグローバル状態を実現できる。テーマ切り替えや認証状態など、更新頻度が低い値に適している。

実装

1. Context と Provider を定義する

// src/contexts/ThemeContext.tsx
import { createContext, useContext, useState } from "react";

type Theme = "light" | "dark";

type ThemeContextValue = {
  theme: Theme;
  toggleTheme: () => void;
};

const ThemeContext = createContext<ThemeContextValue | null>(null);

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<Theme>("light");

  const toggleTheme = () => {
    setTheme((prev) => (prev === "light" ? "dark" : "light"));
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

/** Context の値を取得するカスタムフック */
export function useTheme(): ThemeContextValue {
  const ctx = useContext(ThemeContext);
  if (!ctx) {
    throw new Error("useTheme は ThemeProvider の内側で使用してください");
  }
  return ctx;
}

2. Provider でアプリをラップする

// src/app/layout.tsx
import { ThemeProvider } from "@/contexts/ThemeContext";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ja">
      <body>
        <ThemeProvider>{children}</ThemeProvider>
      </body>
    </html>
  );
}

3. 任意の子コンポーネントで使う

// src/components/ThemeToggle.tsx
"use client";

import { useTheme } from "@/contexts/ThemeContext";

export function ThemeToggle() {
  const { theme, toggleTheme } = useTheme();

  return (
    <button
      onClick={toggleTheme}
      className="rounded border px-3 py-1 text-sm"
    >
      現在: {theme === "light" ? "ライト" : "ダーク"} → 切り替え
    </button>
  );
}

ポイント

  • Context の初期値を null にして、Provider 外での使用をエラーで検出する
  • カスタムフック(useTheme)でアクセスを統一する
  • Next.js App Router で使う場合、Provider コンポーネントは "use client" が必要
  • 頻繁に変わる状態(例: 入力中の値)には適さない。その場合は Zustand を使う

注意点

Context は頻繁に変わる状態には向かない。更新頻度が高い場合は Zustand などを検討する

関連サンプル

同じテーマや技術スタックを使った実装例

  • Context と CSS カスタムプロパティでテーマシステムを構築する

    React Context で現在のテーマを管理し、CSS カスタムプロパティ(CSS 変数)でコンポーネントがテーマを自動追従するシステムを実装する例。

  • Next.js 15 + Zustand でモーダル状態管理を作る

    Zustand を使ってモーダルの開閉状態をグローバルに管理する実装例。複数モーダルへの対応と型安全な設計を示す。

  • React でよく使うフィルタ条件をプリセットとして保存・再適用する

    検索条件(キーワード・カテゴリ・難易度など)をプリセットとして localStorage に保存し、一覧画面からワンクリックで再適用できる UI パターン。

  • useReducer でフォームの状態とバリデーションを一元管理する

    useReducer を使い、複数フィールドのフォーム状態・入力値・バリデーションエラーを単一の reducer で管理する例。外部ライブラリなしで複雑なフォームを扱う。

  • Redux Toolkit の RTK Query で API データフェッチとキャッシュを管理する

    RTK Query の createApi でエンドポイントを定義し、useGetQuery / useMutation フックでデータフェッチ・キャッシュ・自動再フェッチを管理する例。

関連仕様

このサンプルを理解するのに役立つ仕様や概念

  • FrameworkReactUI 構築のための JavaScript ライブラリ。コンポーネントベースで宣言的に UI を記述できる。
←サンプル一覧に戻る