グローバル状態のための useContext
Context を作成し、Provider でサブツリーをラップし、useContext で値を取得して、Props のバケツリレーなしにテーマや認証状態を共有します。
「グローバル状態のための useContext」はCoddyKit上の無料Frontend Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはFrontend Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Frontend Academyコースには全4レッスンが含まれています。
Prop Drilling の問題
Prop drilling とは、深くネストされた子コンポーネントにデータを渡すためだけに、そのデータを使用しない複数の中間コンポーネントを経由して渡すことです。Context を使うと、明示的に渡さなくてもツリー内の任意のコンポーネントで値を利用できるため、この問題を解決できます。
Context の作成
createContext(defaultValue) は Context オブジェクトを作成します。コンポーネントが対応する Provider なしで Context を読み取った場合は、デフォルト値が使用されます。
import { createContext } from 'react';
interface ThemeContextType {
theme: 'light' | 'dark';
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggleTheme: () => {}
});Context の提供
Context を必要とするツリーの部分を Provider でラップします。内部にあるすべてのコンポーネントから Context の値を読み取れます。
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// In app root:
<ThemeProvider>
<App />
</ThemeProvider>useContextで値を取得する
Provider内のすべてのコンポーネントは、useContext(ThemeContext)でコンテキストの値にアクセスできます。propsとして何かを渡す必要はありません。
function ThemeToggle() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'dark' : 'light'} mode
</button>
);
}useContextをラップするカスタムフック
内部でuseContextを呼び出すカスタムフックをエクスポートします。コンテキストを直接公開するよりもコードが整理され、バリデーションも追加できます。
function useTheme() {
const ctx = useContext(ThemeContext);
if (!ctx) throw new Error('useTheme must be used inside ThemeProvider');
return ctx;
}
// Usage:
const { theme } = useTheme();コンテキストによる再レンダリング
Providerの値が変わると、すべてのコンシューマーが再レンダリングされます。値がオブジェクトの場合、レンダリングのたびに新しいオブジェクト参照が作られると、すべてのコンシューマーが再レンダリングされます。これを防ぐには、useMemoで値をメモ化します。
const value = useMemo(
() => ({ theme, toggleTheme }),
[theme] // toggleTheme is stable if created with useCallback
);
<ThemeContext.Provider value={value}>コンテキストを使う場面
適しているもの: テーマ、ロケール、認証済みユーザー、機能フラグ、通知システム。適していないもの: 高頻度の更新(キー入力のたびなど)、大規模で複雑な状態(代わりにストアを使います)。
複数のコンテキスト
独立したコンテキストを複数持つことができます。それぞれの役割を絞り、認証にはAuthContext、テーマにはThemeContextを使います。すべてを保持する単一の万能コンテキストは避けてください。
コンテキストとRedux
Contextは組み込み機能であり、頻繁に変化しないグローバルデータには十分です。Redux/Zustand/Piniaは、多数の更新を伴う複雑な状態や、タイムトラベルデバッグ、ミドルウェアが必要な場合に適しています。
Authコンテキストパターン
よく使われるパターンは、現在のユーザーと認証メソッドを保持するAuthContextです。コンシューマーとなるコンポーネントは、プロップドリリングなしでユーザーを取得できます。
interface AuthContext {
user: User | null;
login: (creds: Credentials) => Promise<void>;
logout: () => void;
}
const AuthCtx = createContext<AuthContext | null>(null);
export const useAuth = () => {
const ctx = useContext(AuthCtx);
if (!ctx) throw new Error('Outside AuthProvider');
return ctx;
};コンテキストとTypeScript
interfaceでコンテキストに型を付けます。初期値にはnullを使い、nullの場合はカスタムフック内で例外をスローします。これにより、「Providerの外で利用された」という本来ありえない状態が、何も起きないまま見過ごされるのを防げます。
パフォーマンス: memo + コンテキスト
React.memoでラップしたコンポーネントは、propsが変わらない限り再レンダリングされません。コンテキストコンシューマーの出力がコンテキストの一部にしか依存しない場合は、不要な再レンダリングを避けるためにコンテキストを分割するか、セレクターパターンを使います。
理解度チェック
Providerが上位に存在しないコンポーネント内でuseContext(MyContext)を呼び出すと、何が返されますか?
復習: useContext
createContextはデフォルト値を持つコンテキストを作成します。ツリーをProviderでラップして値を提供します。内部のどこからでもuseContextで値を読み取れます。カスタムフックでuseContextをラップすると、バリデーションを追加できます。不要な再レンダリングを防ぐため、Providerの値をメモ化します。テーマや認証など、頻繁には変化しないグローバルデータに使用します。
よくある質問
「グローバル状態のための useContext」レッスンは無料ですか?
はい。「グローバル状態のための useContext」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Frontend Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Frontend Academyコースには全4レッスンが含まれています。
「グローバル状態のための useContext」で何を学びますか?
Context を作成し、Provider でサブツリーをラップし、useContext で値を取得して、Props のバケツリレーなしにテーマや認証状態を共有します。 ブラウザで直接実行するハンズオンコードでFrontend Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Frontend Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのFrontend Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「グローバル状態のための useContext」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このFrontend Academyレッスンでコードを書いて実行できますか?
はい。すべてのFrontend Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- グローバル状態のための useContext
- 複雑な状態のための useReducer
- パフォーマンスのための useMemo と useCallback
- カスタム Hook:再利用可能なロジックの抽出