0
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?

More than 1 year has passed since last update.

React useContext()を利用してデータを渡す

Posted at

useContext

useContext()とは、ツリー内の様々な階層からContextに収容されているデータへアクセスすることができます。useContext()を利用することで親コンポーネントから子コンポーネント、子コンポーネントから孫コンポーネントへprposで値を渡さなくても、直接親コンポーネントから孫コンポーネントへ値を渡すことができます。

useContextを利用するために必要なコンポーネント

Context機能を利用するためには以下のコンポーネントが必要になります。

オブジェクト/コンポーネント 説明
Contextオブジェクト React.createContext()の戻り値
Providerコンポーネント Contextオブジェクトが保持しているコンポーネント
Consumerコンポーネント useContext()を利用することで、Contextオブジェクトから値を取得できるコンポーネント

useContextを使用したサンプル1

createContext()を利用してProviderコンポーネントであるSampleProviderコンポーネントとContextオブジェクトであるSampleObjectを作成します。

index.js

index.js
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

SampleProvider.js

SampleProvider.js
// 関数コンポーネント内でceateContextを扱えるようにするためimportする
import React, { createContext } from "react";

// createContext()を利用して、ContextオブジェクトSampleObjectを作成
// 他のファイルでSampleObjectを参照できるようexportする
export const SampleObject = createContext();

// 子コンポーネント(下階層)に渡すtextを定義する
const text = "これはProviderから渡された値";

// 定義したtextの情報を保持するSampleObjcet.Providerを作成する
// SampleObject.Providerでprops.childrenをラップしておくと
// ラップしたコンポーネントのツリー内でContextオブジェクトを
// 参照できるようなるchildrenをpropsで受け取る
export const SampleProvider = (props) => {
  return (

    // 共有したい値をvalue属性の値として渡す
    // value属性の値は、SampleProviderコンポーネントでラップした
    // コンポーネントのツリー内で参照できるようになる
    <SampleObject.Provider value={text}>{props.children}</SampleObject.Provider>
  );
};

App.js

App.js
// SampleProviderコンポーネントをインポートする
import { SampleProvider } from "./SampleProvider";

// Firstコンポーネントをインポートする
import { First } from "./First";

export default function App() {
  return (
    <>
      // SampleProviderでラップしているので、ラップされたFirstコンポーネントの配下で
      // Contextオブジェクトを参照できるようになる
      // Firstコンポーネント配下のコンポーネント(Second、Third)は、Provider内なので、
      // value属性の参照できる
      <SampleProvider>
        <First />
      </SampleProvider>
    </>
  );
}

今回、Contextオブジェクトを保持しているProviderコンポーネンをSampleProviderコンポーネントとして別ファイルに記述していましたが、以下のようにApp.jsに一つにまとめて書くことができます。

App.js
// 関数コンポーネント内でceateContextを扱えるようにするためimportする
import React, { createContext } from "react";

// createContext()を利用して、ContextオブジェクトSampleObjectを作成
// 他のファイルでSampleObjectを参照できるようexportする
export const SampleObject = createContext();

// 子コンポーネント(下階層)に渡すtextを定義する
const text = "これはProviderから渡された値";

// Firstコンポーネントをインポートする
import { First } from "./First";

export default function App() {
  return (
    <>
      
      // SampleObject.Providerでラップするとラップすると、
      // ラップされたコンポーネントのツリー内(First、Second、Third)de
      // value属性の値を参照できるようになる
      <SampleObject.Provider value={text}>

        // Firstコンポーネントは、Provider内なので、value属性の値を参照できる
        <First />
      </SampleObject.Provider>
    </>
  );
}

First.js

First.js
// Secondコンポーネントをインポート
import { Second } from "./Second";

// 他のファイルでFirstコンポーネントを使用できるようexportする
export const First = () => {
  return (
    <>
      <p>Firstコンポーネント</p>
      <Second />
    </>
  );
};

Second.js

Second.js
// Thirdコンポーネントをインポート
import { Third } from "./Third";

// 他のファイルでSecondコンポーネントを使用できるようexportする
export const Second = () => {
  return (
    <>
      <p>Secondコンポーネント</p>
      <Third />
    </>
  );
};

Third.js

Third.js
// 関数コンポーネント内でuseContextを使用できるようインポートする
import React, { useContext } from "react";

// ContextオブジェクトのSampleObjectをインポートする
import { SampleObject } from "./SampleProvider";

// 他のファイルでThirdコンポーネントを使用できるようexportする
// Thirdコンポーネントは、Contextオブジェクトから値を取得できるConsumerコンポーネント
export const Third = () => {

  // useContext()を使用して、Contextオブジェクトから値を取得
  const sampleText = useContext(SampleObject);

  return (
    <>
      <p>
        // sampleTextはProviderコンポーネントから取得したvalueの値
        Thirdコンポーネント: <b>{sampleText}</b>
      </p>
    </>
  );
};

useContextを使用したサンプル2

ProviderコンポーネントからuseState()を使用して保持している値countを受け取ります。

index.js

index.js
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

CountProvider

CountProvider.js
// useState、createContextを使用できるようにインポートする
import React, { useState, createContext } from "react";

// 他のファイルでCountObjectを使用できるようにするためにexportする
// createContext()を使用して、ContextオブジェクトCountObjectを作成
export const CountObject = createContext();

// useStateで定義したcount/setCount情報を保持する
// CountObject.Providerを作成し、props.childrenをラップしておくと、
// CountProviderコンポーネントでラップしたコンポーネントのツリー内で
// Contextオブジェクトを参照できるようになる
// 今回の場合、propsで受け取る値はFirstコンポーネント
export const CountProvider = (props) => {

  // 状態変数count、countを更新する関数setCountを定義する
  const [count, setCount] = useState(0);

  return (

    // value属性の値は、CountProviderコンポーネントでラップした
    // コンポーネントのツリー内(First、Second、Third)で参照できるようになる
    <CountObject.Provider value={[count, setCount]}>
      {props.children}
    </CountObject.Provider>
  );
};

App.js

App.js
// CountProviderコンポーネントをインポートする
import {CountProvider} from "./CountProvider";

// Firstコンポーネントをインポートする
import {First} from "./First";

export default function App() {
  return (
    <>
      // CountProviderでラップしているので、ラップされたFisrtコンポーネントの配下で、
      // Contextオブジェクトの値を参照できるようになる
      // Firstコンポーネント配下のコンポーネントは、Provider内なので、value属性の値を参照できる
      <CountProvider>
        <First />
      </CountProvider>
    </>
  );
}

First.js

First.js
// Secondコンポーネントをインポート
import { Second } from "./Second";

// 他のファイルでFirstコンポーネントを使用できるようexportする
export const First = () => {
  return (
    <>
      <p>Firstコンポーネント</p>
      <Second />
    </>
  );
};

Second.js

Second.js
// Thirdコンポーネントをインポート
import { Third } from "./Third";

// 他のファイルでSecondコンポーネントを使用できるようexportする
export const Second = () => {
  return (
    <>
      <p>Secondコンポーネント</p>
      <Third />
    </>
  );
};

Third.js

Third.js
// useContextを使用できるようインポートする
import React, { useContext } from "react";

// ContextオブジェクトのCountObjectをインポートする
import { CountObject } from "./CountProvider";

// 他のファイルでThirdコンポーネントを利用できるようにするためにexport
// Thirdコンポーネントは、Contextオブジェクトから値を取得できるConsumerコンポーネント
export const Third = () => {

  // useContext()を使用してContextオブジェクトから値を取得
  // [count, setCount]はProviderコンポーネントから取得したvalueの値
  const [count, setCount] = useContext(CountObject);

  // カウントアップする関数countIncrement
  const countIncrement = () => {
    setCount((prevCount) => prevCount + 1);
  };

  // カウントダウンする関数countDecrement
  const countDecrement = () => {
    setCount((prevCount) => prevCount - 1);
  };

  // カウントリセットする関数countReset
  const countReset = () => {
    setCount(0);
  };

  return (
    <>
      <p>
        Thirdコンポーネント:<b>現在のカウント: {count}</b>
      </p>
      <button onClick={countIncrement}>+1ボタン</button>
      <button onClick={countDecrement}>-1ボタン</button>
      <button onClick={countReset}>リセットボタン</button>
    </>
  );
};
0
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
0
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?