4
2

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】初学者、Contextを使ってみる。

Last updated at Posted at 2025-01-19

はじめに

現場でContextを使った実装を任された際に手こずった(現在進行形)ので、もっと単純化してContextの使い方を習得しようという意図をもって作成したものについて備忘録を残します。
本来であればTypescriptで書くべきなのですが、そちらも初学者のため、今回はjavascriptを使って書いています。

Contextとは?

リファレンスを見てみましょう。

「コンテクストを用いると、コンポーネントは props を渡すことなく、離れた親要素から情報を取得できるようになります。例えば、アプリの最上位のコンポーネントが、現在の UI テーマをコンポーネントの階層に関係なくすべてのコンポーネントに渡すことができます。」

説明は上記の通りなのですが、
Contextを使わない場合、propsで「親→子→孫」のように下のコンポーネントに情報を渡していくことになります。しかしこれにはデメリットがあります。

・propsを親から受けて孫に渡すという役割を持つコンポーネントが出来る。
・コンポーネント階層が深くなるとコードが読みにくく、保守性が低下する。

そしてこれらを解決してくれるのが今回のContextということになります。

さっそく作ってみた

今回はContextで管理された値を画面に表示する機能を実装していきます。
完成形はこんな感じ。
image.png

①作成したコンポーネント

App.js
import { Form } from "./Form";
import { TextContainer } from "./TextContainer";
import { TextProvider } from "./TextProvider";

export const App = () => {
  return (
    <div>
      <TextProvider>
        <Form />
        <TextContainer />
      </TextProvider>
    </div>
  );
};

TextProvider:Contextを作成し、値を渡す
Form:テキストボックスとボタン
TextContainer:Contextで管理されている値を表示

②Contextの作成

TextProvider.jsx
import { createContext, useState } from "react";

//コンテキストの作成
export const Text = createContext();

export const TextProvider = ({ children }) => {
  const [texts, setTexts] = useState([]);

  //Formコンポーネントのテキストボックスの内容を配列textsに追加する
  const addText = (inputValue) => {
    setTexts((prev) => [...prev, inputValue]);
  };
  
  //Providerコンポーネントで子コンポーネントを包むことで、Provider配下で利用するコンテキストを決定
  return <Text.Provider value={{ texts, addText }}>{children}</Text.Provider>;
};

まずContextオブジェクトを作成する必要があり、その際にはcreateContextを使用します。
引数は初期値を入れることが出来ます。

//コンテキストの作成
export const Text = createContext();

次に子孫コンポーネントで値を利用できるように、Providerで子コンポーネントを包んであげます。
[作成したコンテキストオブジェクト名].Provider value={渡したい値}という形式で記載し、valueには子孫コンポーネントに渡したい値を書いてあげます。
今回は動的に変化する値を画面に表示させたいのでStateで管理している値を渡しています。

 //Providerコンポーネントで子コンポーネントを包むことで、Provider配下でコンテキストが利用出来る
  return <Text.Provider value={{ texts, addText }}>{children}</Text.Provider>;

③値を画面に表示させる

TextContainer.jsx
import { useContext } from "react";
import { Text } from "./TextProvider";

export const TextContainer = () => {
  //渡された値を使用する
  const { texts, addText } = useContext(Text);

  return (
    <div>
      {texts.map((text, index) => {
        return (
          <div>
            <p>
              <span>{index + 1}.</span>
              {text}
            </p>
          </div>
        );
      })}
    </div>
  );
};

渡されたコンテキストの値を子孫コンポーネント側で使用するためにはuseContextを使います。
useContext(作成したコンテキストオブジェクト名)という形式で使用し、渡された値を受け取ることが出来ます。

 //渡された値を使用する
  const { texts, addText } = useContext(Text);

注意
作成したContextオブジェクトのimportも忘れずにしましょう。
こんなことで時間が溶けてしまいました、、、

import { Text } from "./TextProvider";

④テキストボックスとボタンの作成

Form.jsx
import { useContext, useState } from "react";
import { Text } from "./TextProvider";

export const Form = () => {
  const { texts, addText } = useContext(Text);
  const [value, setValue] = useState();

  const onChangeText = (e) => {
    setValue(e.target.value);
  };

  const handleClick = (value) => {
    addText(value);
    setValue("");
  };

  return (
    <div>
      <input value={value} onChange={onChangeText} />

      <button
        onClick={() => {
          handleClick(value);
        }}
      >
        追加
      </button>
    </div>
  );
};

Contextで管理されているaddTextを使用するためにuseContextを使って値を受け取っています。

完成

image.png

4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?