1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React学習記録】 useContext

Last updated at Posted at 2025-03-12

React hooks【useContext】

useContextを使用することでグローバルな状態を作成し、コンポーネントツリーのどこからでもコンテキストの値を簡単に取得できる。通常、親コンポーネントから子コンポーネントへpropsを渡す必要があるが、useContextを使うことで、深い階層のコンポーネントにも直接データを提供できる。これにより、props を何階層も渡す 「props drilling」、いわゆるバケツリレーを避けられる。

useContext の基本概念

  • Context API: React の組み込み機能で、アプリケーション内でデータを グローバルに共有 するための仕組み。
  • useContext: コンポーネント内で、Context で提供されたデータにアクセスするためのフック。

使用例 (モードの切り替え機能)

フォルダ構成

/src
 ├── components
 │    ├── Parent.jsx
 │    ├── Child.jsx
 │    ├── GrandChild.jsx
 ├── context
 │    ├── ThemeContext.jsx  ← Context を定義
 ├── App.jsx

1:ThemeContext.jsx

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

// Context を作成
const ThemeContext = createContext();

// Provider コンポーネントを作成
export function ThemeProvider({ children }) {
  const [theme, setTheme] = useState("light");

  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// ThemeContext をエクスポート
export { ThemeContext };

2:App.jsx

import { ThemeProvider } from "./context/ThemeContext";
import Parent from "./components/Parent";

function App() {
  return (
    <ThemeProvider>
      <Parent /> // 親コンポーネント呼び出し
    </ThemeProvider>
  );
}

export default App;

3:Parent.jsx

import Child from "./Child";

function Parent() {
  return <Child />; // 子コンポーネント呼び出し。useContext のおかげで props を渡す必要がない
}

export default Parent;

4:Child.jsx

import GrandChild from "./GrandChild";

function Child() {
  return <GrandChild />; // 孫コンポーネント呼び出し。props を中継せずに済む
}

export default Child;

5:GrandChild.jsx

import { useContext } from "react";
import { ThemeContext } from "../context/ThemeContext";

function GrandChild() {
  // useContext で直接テーマと切り替え関数を取得
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <div style={{ background: theme === "light" ? "#fff" : "#333", color: theme === "light" ? "#000" : "#fff", padding: "20px" }}>
      <p>現在のテーマ: {theme}</p>
      <button onClick={toggleTheme}>テーマを切り替え</button>
    </div>
  );
}

export default GrandChild;

上記コードでは、親コンポーネントである Parent.jsx から props のバケツリレーを行わずに孫コンポーネントの GrandChild.jsx で Context にアクセスすることができ、テーマの変更処理を行うことができる。使用しなかった場合は以下のようになると考えられる。


useContext を使用しない場合の例

以下は、useContext を使わず props でデータを伝播する例。フォルダ構成は useContext 使用時と同じ(/src/components/ 配下に Parent.jsx, Child.jsx, GrandChild.jsx)を前提とする。

1:App.jsx (useContext不使用)

import { useState } from "react";
import Parent from "./components/Parent";

function App() {
  const [theme, setTheme] = useState("light");

  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return (
    <Parent theme={theme} toggleTheme={toggleTheme} />
  );
}

export default App;

2:Parent.jsx (useContext不使用)

import Child from "./Child";

function Parent({ theme, toggleTheme }) {
  return <Child theme={theme} toggleTheme={toggleTheme} />;
}

export default Parent;

3:Child.jsx (useContext不使用)

import GrandChild from "./GrandChild";

function Child({ theme, toggleTheme }) {
  return <GrandChild theme={theme} toggleTheme={toggleTheme} />;
}

export default Child;

4:GrandChild.jsx (useContext不使用)

function GrandChild({ theme, toggleTheme }) {
  return (
    <div style={{ background: theme === "light" ? "#fff" : "#333", color: theme === "light" ? "#000" : "#fff", padding: "20px" }}>
      <p>現在のテーマ: {theme}</p>
      <button onClick={toggleTheme}>テーマを切り替え</button>
    </div>
  );
}

export default GrandChild;

useContext を使用せずに、props を使ってテーマの状態を親コンポーネントから子・孫コンポーネントに伝播しているが、コンポーネント間でのデータの受け渡しが煩雑になる。

このように useContext を使用することでコンポーネントの管理がしやすく、コード量が減り、再利用性が高く、シンプルで効率的な状態共有が可能となる。
アプリケーション全体で共通の情報(テーマや認証情報など)を管理する場合に非常に有効。

補足

Context に渡すデータが変化すると、そのデータを利用しているすべてのコンポーネントが再レンダリングされるため、頻繁に変更されるデータを Context に渡すとパフォーマンスの問題が発生する可能性があるため注意。

対策:

  • コンテキストの分割: 頻繁に更新されるデータとそうでないデータを別の Context に分ける。
  • メモ化: useMemouseCallback を使って、Context の値や関数が不必要に再生成されないようにする。
    例:
    const value = useMemo(() => ({ theme, toggleTheme }), [theme]);
    return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
    

これにより、不要な再レンダリングを減らせる。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?