React学習記録 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>
  );
}

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/>; //子コンポーネント呼び出し 
}

export default Parent;

4:Child.jsx

import GrandChild from "./GrandChild";

function Child() {
  return <GrandChild/>; //孫コンポーネント呼び出し  
}

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にアクセスすることができ、テーマの変更処理を行うことができる。使用しなかった場合は以下のようになると考えられる。

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 に渡すとパフォーマンスの問題が発生する可能性があるため注意

いいなと思ったら応援しよう!

この記事が参加している募集