0Pricing
Frontend Academy · レッスン

グローバル状態のための 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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. グローバル状態のための useContext
  2. 複雑な状態のための useReducer
  3. パフォーマンスのための useMemo と useCallback
  4. カスタム Hook:再利用可能なロジックの抽出
← Frontend Academyに戻る