こんにちは!Reactの学習、楽しく進められていますか?
「コンポーネント同士でデータの受け渡しをしたいだけなのに、なんだか親から子へ、子から孫へと、バケツリレーみたいにpropsを渡していくのが大変……」
「どこでどんな状態を持っているのか、自分でも分からなくなってきた……」
Reactを触り始めて少し経つと、誰もが一度はこの「プロップス・バケツリレー地獄」に直面します。大丈夫です、安心してください。みんな最初はそこで頭を抱えますし、私も昔はよく迷子になっていました。
そんな時にお助けヒーローとして登場するのが、今回学ぶ「useContext(コンテキスト)」です!
今回は、難しい専門用語はいったん脇に置いて、身近な例えを交えながら「コンテキストプロバイダー」の作り方を一緒に優しく紐解いていきましょう。
—
1. コンテキスト(Context)って、例えるならどんなもの?
プログラムのコードを見る前に、まずはイメージを掴みましょう。
Reactのコンポーネントは、よく「家族の家」に例えられます。
一番上の階(親)にいるお父さんが持っている「お財布(データ)」を、一番下の階(孫)にいる子どもが使いたいとします。
通常の`props`(プロップス)を使ったバケツリレーだと、こうなります。
- お父さん $\rightarrow$ 子ども $\rightarrow$ 孫 へ、「これ持ってて」「はい、次持ってて」と、途中の部屋を通る全員に財布を渡していかないといけません。面倒ですよね。途中で誰かが落としてしまうかもしれません。
そこで登場するのが、「リビングの中心に置かれた、家族みんなが自由に使えるお菓子ボックス」です。これがContext(コンテキスト)のイメージです。
リビングにお菓子ボックス(Provider)をポンと置いておけば、家の中のどこにいる家族(コンポーネント)だって、わざわざ誰かにお願いしなくても、勝手にそこへ行って必要なときにお菓子を取り出せますよね。
ReactのContextもこれと全く同じで、「アプリ全体のどこからでも、直接アクセスできるデータの共有スペース」を作ることができる仕組みなんです。
—
2. お店で体験してみよう!「テーマ切り替え」のProviderを作ってみる
では、実際に手を動かして、アプリ全体で「ダークモード(黒い画面)」と「ライトモード(白い画面)」を切り替えるためのProvider(お菓子ボックスの置き場所)を作ってみましょう。
ここでは、次の3つのステップで進めます。
1. Contextを作る(共有スペースの土地を確保する)
2. Providerを作る(データを配る係のコンポーネントを用意する)
3. 使う(どこからでもデータを呼び出す)
実際のコードを見てみてください。コメントもたっぷり書いておきました!
実装コード
import React, { createContext, useContext, useState } from ‘react’;
// ———————————————————————-
// ステップ1: 共有スペース(Context)を作る
// ———————————————————————-
// 「ここでテーマの情報を共有しますよ」という看板を立てるイメージです。
// 初期値として、とりあえず空っぽのオブジェクトを渡しておきます。
const ThemeContext = createContext();
// ———————————————————————-
// ステップ2: Provider(プロバイダー)を作る
// ———————————————————————-
// 子どもたちにデータを配る「お母さん」のような役割を持つコンポーネントです。
export function ThemeProvider({ children }) {
// 状態管理(useState):いま何モードか?(初期値は ‘light’)
const [theme, setTheme] = useState(‘light’);
// テーマを切り替えるための優しい魔法の関数
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === ‘light’ ? ‘dark’ : ‘light’));
};
// 共有したいデータや関数をまとめておきます
const value = {
theme,
toggleTheme,
};
// ThemeContext.Provider で囲んだエリアの中にいる子孫たちは、
// すべて value の中身(theme と toggleTheme)を使えるようになります!
return (
{/ children とは、この Provider で挟んだ「中にあるコンポーネントたち」のことです /}
{children}
);
}
// ———————————————————————-
// おまけ:専用のカスタムフックを作っておくと、使うときもっとラクになります!
// ———————————————————————-
export function useTheme() {
return useContext(ThemeContext);
}
—
3. 作ったProviderをアプリで使ってみよう!
先ほど作った `ThemeProvider` は、いわば「魔法のバリア」のようなものです。このバリアの内側にいるコンポーネントだけが、テーマのデータを受け取ることができます。
アプリのいちばん大元(`App.js` など)で、次のように包んであげましょう。
// App.jsx
import React from ‘react’;
import { ThemeProvider, useTheme } from ‘./ThemeContext’; // さっきのファイルを読み込む
// 実際にテーマの色が変わるのを画面に表示する子孫コンポーネント
function ThemedCard() {
// 専用のフックを使って、共有データ(theme と toggleTheme)をゲット!
// バケツリレーは一切していません。すごいスッキリ!
const { theme, toggleTheme } = useTheme();
// テーマに応じたスタイルを定義
const style = {
backgroundColor: theme === ‘light’ ? ‘#ffffff’ : ‘#333333’,
color: theme === ‘light’ ? ‘#000000’ : ‘#ffffff’,
padding: ’20px’,
borderRadius: ‘8px’,
textAlign: ‘center’,
margin: ’20px’,
border: ‘1px solid #ccc’,
};
return (
現在のモードは: {theme} です!
);
}
// アプリの根っこ
export default function App() {
return (
/
ここに ThemeProvider を置くことで、
この中にあるすべてのコンポーネントでテーマが共有されます!
/
useContextのサンプルアプリへようこそ!
);
}
これで、`App` の中にある `ThemedCard` は、親から何個も `props` を受け取ることなく、直接「いま何モードか?」を知り、ボタンを押してモードを変えることができるようになりました!
—
4. 初学者がハマりがちな「つまずきポイント」と処方箋
Contextを使うとき、初心者のうちはいくつか「あれ?」と手が止まる瞬間があります。代表的なものをそっとシェアしておきますね。
つまずき①:`undefined` エラーが出る
症状: 「Cannot read properties of undefined (reading ‘theme’)」といったエラーが出る。
原因: `useContext` を使っているコンポーネントが、`ThemeProvider` の外側(バリアの外)に配置されてしまっています。
対策: 「データを配る側(Provider)」でしっかりとコンポーネントが包まれているか、ツリー構造を確認してみましょう。
つまずき②:何でもかんでもContextに入れちゃう問題
症状: アプリのすべての状態(入力フォームの文字など)をContextに入れようとして、コードがごちゃごちゃになる。
原因: 便利だからといって全部をグローバル(全体共有)にすると、アプリの動きが重くなったり、どこでデータが書き換わっているか追えなくなります。
対策: 「ログイン中のユーザー情報」や「画面のテーマ(ダークモード)」など、アプリのあちこちで本当に必要とされる大元の情報だけに絞るのが、綺麗に保つコツです。普通の局所的なデータは、今まで通り普通の `useState` と `props` で十分ですよ!
—
さいごに
コンテキストプロバイダーの構築、いかがでしたでしょうか?
最初は「お呪い(おまじない)みたいだな」と感じるかもしれませんが、自分で書いて動かしてみると、「あ、バケツリレーしなくていいからコードがめちゃくちゃスッキリする!」と感動する瞬間が必ずやってきます。
焦らず、一歩ずつ、ご自身のペースでエディタにコードを打ち込んで試してみてくださいね。あなたのReactライフを、心から応援しています!

コメント