React useContextによるテーマ管理 — ダークモードとテーマ切り替え

React useContextでテーマ切り替えを実装します。ThemeProviderの作成、コンテキストの消費、テーマ付きアプリケーションでの不要な再レンダリングの回避に関する完全ガイド。

Context Hooks

詳細な説明

useContextによるテーマシステムの構築

useContextはReactコンテキストから値を読み取り、propドリリングなしでコンポーネント間でデータを共有できます。テーマ管理は最も象徴的なユースケースの一つです。

テーマコンテキストの作成

import { createContext, useContext, useState } from "react";

type Theme = "light" | "dark";

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

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

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

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

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

カスタムフックの作成

useContextをカスタムフックでラップすることで、DXが向上しランタイム検証が可能になります:

export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error("useTheme must be used within a ThemeProvider");
  }
  return context;
}

パフォーマンスの最適化

コンテキスト値が変更されると、すべてのコンシューマーが再レンダリングされます。最適化するには:

  1. useMemoでvalueオブジェクトをメモ化し、毎レンダリングでの新しい参照を防ぐ
  2. 更新頻度でコンテキストを分割する
  3. コンテキストを直接消費しない子コンポーネントにReact.memoを使用する

ユースケース

テーマ管理、認証、ロケール、フィーチャーフラグ、そして異なるネストレベルの多くのコンポーネントが明示的なprop渡しなしにアクセスする必要のあるデータにuseContextを使用します。

試してみる — React Hooks Reference

フルツールを開く