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;
}
パフォーマンスの最適化
コンテキスト値が変更されると、すべてのコンシューマーが再レンダリングされます。最適化するには:
- useMemoでvalueオブジェクトをメモ化し、毎レンダリングでの新しい参照を防ぐ
- 更新頻度でコンテキストを分割する
- コンテキストを直接消費しない子コンポーネントにReact.memoを使用する
ユースケース
テーマ管理、認証、ロケール、フィーチャーフラグ、そして異なるネストレベルの多くのコンポーネントが明示的なprop渡しなしにアクセスする必要のあるデータにuseContextを使用します。