カテゴリ: React 更新日: 2026/03/20

ReactのcreateContextとuseContextの使い方を完全解説!初心者でもわかるContext APIの基本

createContextとuseContextの基本的な使い方
createContextとuseContextの基本的な使い方

先生と生徒の会話形式で理解しよう

生徒

「createContextとuseContextって名前が似ていてどう違うのかよくわかりません。」

先生

「createContextはデータを入れる「箱」を作る関数で、useContextはその箱からデータを取り出すフックです。役割がまったく違うので、ひとつずつ覚えていきましょう。」

生徒

「実際にどう書けばいいか、コードで見せてもらえますか?」

先生

「もちろんです。シンプルな例から順番に確認していきましょう!」

1. createContextとuseContextの役割を整理しよう

1. createContextとuseContextの役割を整理しよう
1. createContextとuseContextの役割を整理しよう

ReactのContext APIを使うとき、中心になる関数がcreateContextuseContextの2つです。まずはそれぞれの役割をしっかり理解しておきましょう。

createContextは、データを保管するための「共有の箱」を作る関数です。この箱のことをContextオブジェクトと呼びます。箱を作るときに初期値を設定することができます。作った箱はProviderというコンポーネントを通じて、アプリ内の好きな範囲にデータを提供します。

useContextは、その箱からデータを取り出すためのフックです。フックとは、Reactが用意している特別な関数で、コンポーネントの中でReactの機能を使えるようにするものです。useContextを呼び出すと、近くにあるProviderからデータを受け取ることができます。

ふたつの関係をまとめると、createContextで箱を作り、Providerでデータを入れて、useContextでデータを取り出す、という流れになります。この3ステップがContext APIの基本の型です。

2. createContextの書き方と初期値の設定方法

2. createContextの書き方と初期値の設定方法
2. createContextの書き方と初期値の設定方法

createContextの基本的な書き方を見ていきましょう。Reactからインポートして呼び出すだけで、Contextオブジェクトが作成できます。


import { createContext } from "react";

// 初期値として空文字を設定したContextを作成
const MessageContext = createContext("");

// 初期値として数値を設定したContextを作成
const CountContext = createContext(0);

// 初期値としてオブジェクトを設定したContextを作成
const UserContext = createContext({ name: "", age: 0 });
このコードはContextオブジェクトを作るだけのファイルです。画面への表示はありませんが、これをimportすることでアプリ内のどこからでもデータを共有できるようになります。

createContext()の引数に渡した値が初期値になります。初期値とは、Providerがない状態でuseContextを呼び出したときに返ってくる値です。実際の開発では必ずProviderを使うので、この初期値が使われることはあまりありませんが、TypeScriptなど型の情報を伝える目的で設定することが多いです。

作成したContextオブジェクトはexportして他のファイルから使えるようにしておくのが一般的な書き方です。

3. Providerを使ってデータを提供する方法

3. Providerを使ってデータを提供する方法
3. Providerを使ってデータを提供する方法

createContextで作ったContextオブジェクトには、Providerというコンポーネントが付属しています。このProviderで子コンポーネントを囲み、value属性にデータをセットすることで、囲まれた範囲のすべてのコンポーネントにデータが提供されます。


import React, { createContext } from "react";

// Contextを作成してエクスポート
export const ThemeContext = createContext("light");

function App() {
  const currentTheme = "dark";

  return (
    // ThemeContext.Providerでアプリをラップしてvalueにデータをセット
    <ThemeContext.Provider value={currentTheme}>
      <div>
        <h1>テーマ設定のサンプル</h1>
        <ChildComponent />
      </div>
    </ThemeContext.Provider>
  );
}

function ChildComponent() {
  return <p>子コンポーネントです</p>;
}

export default App;
画面に「テーマ設定のサンプル」と「子コンポーネントです」が表示されます。この状態では、ThemeContext.Providerの内側にあるすべてのコンポーネントが「dark」というデータを取り出せる準備が整っています。

valueに渡すデータは文字列だけでなく、数値、真偽値(trueかfalse)、配列、オブジェクトなど何でも設定できます。複数の値をまとめて渡したい場合はオブジェクトにまとめて渡すのが一般的です。

4. useContextでデータを取り出してみよう

4. useContextでデータを取り出してみよう
4. useContextでデータを取り出してみよう

Providerで提供されたデータは、useContextフックを使って取り出します。引数にContextオブジェクトを渡すだけで、Providerからセットされたデータを受け取れます。先ほどのテーマ設定の例を完成させてみましょう。


import React, { createContext, useContext } from "react";

const ThemeContext = createContext("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Header />
      <MainContent />
    </ThemeContext.Provider>
  );
}

function Header() {
  // useContextでThemeContextからデータを取得
  const theme = useContext(ThemeContext);
  return (
    <header style={{ background: theme === "dark" ? "#333" : "#fff", color: theme === "dark" ? "#fff" : "#000", padding: "10px" }}>
      <p>現在のテーマ:{theme}</p>
    </header>
  );
}

function MainContent() {
  const theme = useContext(ThemeContext);
  return (
    <main style={{ background: theme === "dark" ? "#555" : "#f5f5f5", padding: "10px" }}>
      <p>メインコンテンツエリアです</p>
    </main>
  );
}

export default App;
画面のヘッダーが暗い背景に白い文字で表示され、「現在のテーマ:dark」と表示されます。メインコンテンツエリアも暗い背景になります。HeaderとMainContentはどちらもuseContextを使ってThemeContextから直接テーマ情報を取得しています。

複数のコンポーネントが同じContextからデータを取り出せることが確認できます。propsを使った場合は親から子へ渡す必要がありましたが、useContextを使えば各コンポーネントが直接取得できます。

5. useStateと組み合わせてデータの変更にも対応しよう

5. useStateと組み合わせてデータの変更にも対応しよう
5. useStateと組み合わせてデータの変更にも対応しよう

Contextはデータを読むだけでなく、useStateと組み合わせることで、データの変更も全コンポーネントに反映できるようになります。useStateとは、コンポーネントの中で変化する値を管理するためのReactフックです。

ProviderのvalueにuseStateの値と更新関数をまとめて渡すことで、子孫コンポーネントからContextの値を書き換えることができます。


import React, { createContext, useContext, useState } from "react";

const LanguageContext = createContext(null);

function App() {
  const [language, setLanguage] = useState("日本語");

  return (
    // valueにオブジェクトとして値と更新関数をまとめて渡す
    <LanguageContext.Provider value={{ language, setLanguage }}>
      <LanguageSelector />
      <Greeting />
    </LanguageContext.Provider>
  );
}

function LanguageSelector() {
  const { setLanguage } = useContext(LanguageContext);
  return (
    <div>
      <button onClick={() => setLanguage("日本語")}>日本語</button>
      <button onClick={() => setLanguage("English")}>English</button>
    </div>
  );
}

function Greeting() {
  const { language } = useContext(LanguageContext);
  return <p>選択中の言語:{language}</p>;
}

export default App;
画面に「日本語」「English」のボタンが表示され、「選択中の言語:日本語」と表示されます。「English」ボタンを押すと「選択中の言語:English」に切り替わります。LanguageSelectorとGreetingはpropsのやり取りなしにデータを共有しています。

このようにuseStateとContextを組み合わせると、状態の読み取りと更新を両方Contextで管理できます。更新関数も一緒にvalueに含めるのがポイントです。

6. Contextの定義を別ファイルに切り出す書き方

6. Contextの定義を別ファイルに切り出す書き方
6. Contextの定義を別ファイルに切り出す書き方

実際のアプリ開発では、Contextの作成とProviderコンポーネントを専用ファイルに切り出して管理するのが主流のやり方です。ファイルを分けることで、コードの見通しがよくなり、チームでの開発でも扱いやすくなります。

たとえばUserContext.jsxというファイルを作り、そこにContextとProviderをまとめて定義します。


// UserContext.jsx
import { createContext, useContext, useState } from "react";

// ContextをエクスポートしてどこからでもuseContextで使えるようにする
export const UserContext = createContext(null);

// カスタムフック:useContextをラップして使いやすくする
export function useUser() {
  return useContext(UserContext);
}

// Providerコンポーネントをエクスポート
export function UserProvider({ children }) {
  const [user, setUser] = useState({ name: "ゲスト", isLoggedIn: false });

  const login = (name) => {
    setUser({ name: name, isLoggedIn: true });
  };

  const logout = () => {
    setUser({ name: "ゲスト", isLoggedIn: false });
  };

  return (
    <UserContext.Provider value={{ user, login, logout }}>
      {children}
    </UserContext.Provider>
  );
}

このファイルを使うAppコンポーネントは次のように書きます。


// App.jsx
import React from "react";
import { UserProvider, useUser } from "./UserContext";

function UserStatus() {
  const { user, login, logout } = useUser();

  return (
    <div>
      <p>{user.isLoggedIn ? user.name + "さんがログイン中" : "ログアウト中"}</p>
      {user.isLoggedIn ? (
        <button onClick={logout}>ログアウト</button>
      ) : (
        <button onClick={() => login("田中")}>田中さんでログイン</button>
      )}
    </div>
  );
}

function App() {
  return (
    <UserProvider>
      <h1>ログイン状態の管理</h1>
      <UserStatus />
    </UserProvider>
  );
}

export default App;
画面に「ログアウト中」と「田中さんでログイン」ボタンが表示されます。ボタンを押すと「田中さんがログイン中」に切り替わり、「ログアウト」ボタンを押すと元に戻ります。

コードの中でuseUser()というカスタムフックを作っているのがポイントです。カスタムフックとは、useContextなどのフックをラップして、より使いやすい形にした独自の関数のことです。毎回useContext(UserContext)と書く代わりにuseUser()と短く書けるようになります。

7. useContextを使うときによくあるエラーと対処法

7. useContextを使うときによくあるエラーと対処法
7. useContextを使うときによくあるエラーと対処法

useContextを使い始めたころにつまずきやすいポイントをいくつか紹介します。知っておくと、エラーが出たときにすぐ原因を特定できます。

まず多いのが、Providerの外でuseContextを使ってしまうケースです。useContextはProviderで囲まれた範囲の内側にあるコンポーネントでしか正しく動作しません。Providerの外で呼び出した場合、createContextで指定した初期値が返ってきます。初期値をnullにしている場合はエラーになることもあるため注意が必要です。

次に、インポートを忘れてしまうケースもよくあります。useContextはReactからインポートが必要です。また、createContextで作ったContextオブジェクトをインポートし忘れることもあるため、ファイルの先頭のインポート文を確認する習慣をつけましょう。

また、Providerのvalueの書き方のミスも注意が必要です。オブジェクトを渡すときはvalue={{ key: value }}のように二重の波かっこになります。外側の波かっこはJSXの式を書くためのもので、内側の波かっこがオブジェクトのリテラルです。一重にしてしまうと文法エラーになります。

エラーが出たときは、まずProviderで正しく囲まれているか、インポートは正しいか、valueの書き方は合っているかの3点を確認するとほとんどの場合解決できます。

カテゴリの一覧へ
新着記事
New1
React
ReactのcreateContextとuseContextの使い方を完全解説!初心者でもわかるContext APIの基本
New2
Next.js
Next.js Pages Routerでページごとのレイアウトを簡単に実現する方法!初心者向け完全ガイド
New3
Next.js
Next.js Pages RouterとReact Routerの違いを初心者向けに徹底解説!Next.jsルーティング入門
New4
React
ReactのuseEffectでローディング状態を管理する方法を解説!初心者でもできる非同期処理の基本
人気記事
No.1
Java&Spring記事人気No1
React
ReactとTypeScriptの環境構築をやさしく解説!Viteとtsconfigの設定も丁寧に紹介
No.2
Java&Spring記事人気No2
React
Reactでフォーカスイベントを制御する方法!onFocusとonBlurを初心者向けに解説
No.3
Java&Spring記事人気No3
React
Reactとは?初心者でもわかるReact.jsの基本概念と特徴をやさしく解説
No.4
Java&Spring記事人気No4
React
ReactでAxiosのPUT・DELETEリクエストを完全ガイド!初心者でもわかるAPI通信の基本
No.5
Java&Spring記事人気No5
React
ReactのJSXとJavaScriptの違いを完全ガイド!初心者でもわかるReactのJSX入門
No.6
Java&Spring記事人気No6
React
コンポーネントの作り方!基本的な書き方と使い方をReact初心者向けに解説
No.7
Java&Spring記事人気No7
React
Reactで再利用可能なリスト表示コンポーネントを実装しよう!初心者でもわかるReactのコンポーネント分割
No.8
Java&Spring記事人気No8
Next.js
Next.jsのRoute Groupの使い方を完全ガイド!App Routerでフォルダ構成を整理する方法