はじめに
Reactではコンポーネント間で値を共有する際、propsを使うのが基本です。
しかし、ツリーの深い場所まで同じデータを渡す場合は、バケツリレー が発生しがちです。
このような煩雑さを解決してくれるのが、ReactのContext APIです。
本記事では、Context の概要や用途、サンプルコードなどを記載します。
Contextとは?
“Context lets a component receive information from a parent component without explicitly passing it through every level of the tree.”
— Passing Data Deeply with Context
ReactのContext APIは、ツリー構造の深い位置にあるコンポーネントでも、親から明示的にpropsを渡さずに値を受け取れる仕組みです。
例えば、次のようにProviderで囲っておけば、どの深さの子コンポーネントからでもその値にアクセスできます。
<MyContext.Provider value={...}>
<App />
</MyContext.Provider>
Contextが向いている場面
Context の実際の用途としては、以下のような「アプリ全体(異なる複数階層のコンポーネント)で使われる、めったに変わらない値」に適しています。
- テーマ設定(ライト/ダーク)
- 現在の言語(i18n)
- ログインユーザー情報
逆に「フォームの入力内容」や「一時的なUI状態」など、頻繁に変わるデータには向いていません。Contextで扱うと、パフォーマンスの低下やコードの複雑化を招く可能性があります。
実装サンプル
本記事では、以下のような string型の配列を2つContextで管理する例を紹介します。
名前 | 内容 |
---|---|
fruitChoices |
果物の選択肢(例:りんご、バナナ) |
vegetableChoices |
野菜の選択肢(例:にんじん、ピーマン) |
あくまで Context の実装方法をわかりやすく伝えるためのサンプルです。中身はただの定数なので、実用途としては、わざわざ Context 化する必要はないです。
開発環境
開発環境は以下の通りです。
- Windows11
- React 18.3.1
- React Router 7.5.2
- TypeScript 5.8.3
- Vite 6.3.4
- Node.js 22.13.1
- npm 11.0.0
1. Contextの定義とProviderの作成
import { createContext, ReactNode, useContext } from "react";
type ChoiceContextType = {
fruitChoices: string[];
vegetableChoices: string[];
};
const ChoiceContext = createContext<ChoiceContextType>({
fruitChoices: [],
vegetableChoices: [],
});
export const ChoiceProvider = ({ children }: { children: ReactNode }) => {
const fruitChoices = ["りんご", "みかん", "バナナ"];
const vegetableChoices = ["にんじん", "ほうれん草", "ピーマン"];
return (
<ChoiceContext.Provider value={{ fruitChoices, vegetableChoices }}>
{children}
</ChoiceContext.Provider>
);
};
/** Contextの値を取得するカスタムフック */
export const useChoices = () => useContext(ChoiceContext);
- 初期値を
createContext
にそのまま渡すことで、型をシンプルにしています(undefined
チェックも不要)
2. Provider で Context で保持した状態を利用するコンポーネント全体をラップする
import { Route, Routes } from "react-router-dom";
import ChoiceViewer from "./pages/ChoiceViewer";
import { ChoiceProvider } from "./contexts/ChoiceContext";
import { NotFount } from "./pages/NotFound";
function App() {
return (
<Routes>
<Route
path="/choice-viewer"
element={
<ChoiceProvider>
<ChoiceViewer />
</ChoiceProvider>
}
/>
<Route path="*" element={<NotFount />} />
</Routes>
);
}
export default App;
3. Contextを使って値を表示する
import { useChoices } from "./ChoiceContext";
const ChoiceViewer = () => {
const { fruitChoices, vegetableChoices } = useChoices();
return (
<div>
<h3>果物の選択肢</h3>
<ul>
{fruitChoices.map((fruit) => (
<li key={fruit}>{fruit}</li>
))}
</ul>
<h3>野菜の選択肢</h3>
<ul>
{vegetableChoices.map((vegetable) => (
<li key={vegetable}>{vegetable}</li>
))}
</ul>
</div>
);
};
export default ChoiceViewer;
まとめ
この記事では、ReactのContext APIについて解説しました。Contextを適切に活用することで、コードの可読性と保守性を高め、「バケツリレー」問題から解放された効率的なコンポーネント設計が可能になります。