React useContext Hook
1. React Contextとは?
React Contextは、ステート(State)をグローバルに管理するための仕組みです。
useState フック単体で管理する場合よりも、深くネスト(階層化)されたコンポーネント間でステートをはるかに簡単に共有することができます。
1.1 課題:プロップ・ドリリング(Prop Drilling)
通常、ステートはアクセスを必要とするコンポーネント群の中で、最も上位にある親コンポーネントが保持すべきです。
しかし、多くのコンポーネントがネストされている場合、最上位と最下位のコンポーネントで同じステートを使いたいとき、Contextなしでは各コンポーネントに「プロップス(Props)」としてステートをバケツリレーのように渡していく必要があります。これを 「プロップ・ドリリング(Prop Drilling)」 と呼びます。
実装例:ネストされたコンポーネントへのプロップス渡し
import { useState } from 'react';
import { createRoot } from 'react-dom/client';
function Component1() {
const [user, setUser] = useState("ライナス");
return (
<>
<h1>{`こんにちは、${user}さん!`}</h1>
{/* userをComponent2に渡す */}
<Component2 user={user} />
</>
);
}
function Component2({ user }) {
return (
<>
<h1>コンポーネント 2</h1>
{/* Component2自体はuserを必要としないが、Component3のために渡す必要がある */}
<Component3 user={user} />
</>
);
}
function Component3({ user }) {
return (
<>
<h1>コンポーネント 3</h1>
<h2>{`また会いましたね、${user}さん!`}</h2>
</>
);
}
createRoot(document.getElementById('root')).render(
<Component1 />
);この例では、Component2 はステートを必要としていないにもかかわらず、Component3 に届けるためだけにステートを中継しなければなりません。これが開発における「無駄な仲介」となります。
2. React Contextによる解決策
この問題を解決するために、Context(コンテキスト)を作成します。
2.1 Contextの作成
Contextを作成するには、createContext をインポートして初期化します。
import { useState, createContext, useContext } from 'react';
import { createRoot } from 'react-dom/client';
// Contextの初期化
const UserContext = createContext();次に、ステートを必要とするコンポーネントツリーを Context Provider(コンテキスト・プロバイダー) でラップします。
2.2 Context Provider
子コンポーネントをプロバイダーでラップし、共有したい値を value 属性に指定します。
function Component1() {
const [user, setUser] = useState("ライナス");
return (
<UserContext.Provider value={user}>
<h1>{`こんにちは、${user}さん!`}</h1>
<Component2 />
</UserContext.Provider>
);
}これで、このツリーに含まれるすべてのコンポーネントが user コンテキストに直接アクセスできるようになります。
2.3 useContextフックの利用
子コンポーネントでコンテキストを使用するには、useContext フックを介してアクセスします。まず、インポートに useContext を含めてください。
import { useState, createContext, useContext } from "react";これで、すべてのコンポーネントで user コンテキストを呼び出すことができます。
function Component3() {
// useContextでContextの値を直接取得
const user = useContext(UserContext);
return (
<>
<h1>コンポーネント 3</h1>
<h2>{`また会いましたね、${user}さん!`}</h2>
</>
);
}3. 実装の完全なコード例
React Contextを使用した最終的なコード構成は以下のようになります。
import { useState, createContext, useContext } from 'react';
import { createRoot } from 'react-dom/client';
// 1. Contextを作成
const UserContext = createContext();
function Component1() {
const [user, setUser] = useState("ライナス");
return (
// 2. Providerでラップして値を共有
<UserContext.Provider value={user}>
<h1>{`こんにちは、${user}さん!`}</h1>
<Component2 />
</UserContext.Provider>
);
}
function Component2() {
return (
<>
<h1>コンポーネント 2</h1>
{/* Component2は何もプロップスを受け取らず、渡さない */}
<Component3 />
</>
);
}
function Component3() {
// 3. useContextを使用して必要なコンポーネントでデータを受け取る
const user = useContext(UserContext);
return (
<>
<h1>コンポーネント 3</h1>
<h2>{`また会いましたね、${user}さん!`}</h2>
</>
);
}
createRoot(document.getElementById('root')).render(
<Component1 />
);