LoginSignup
0
0

[React]useContext

Posted at

useContextとは

  • 上位コンポーネントで用意された値を、任意の子孫コンポーネントで使用できる仕組み。
  • propsのバケツリレーを解消する。
  • ただし、上位コンポーネントでのコンテキスト登録が前提となり、再利用性がなくなる。そのため安易に多用はしない。

useContextによるデータ受け渡しの流れ

以下の3ステップを踏む。

  1. コンテキストの作成
    createContextでコンテキストを作成し公開する。
  2. コンテキストタグで囲み、値を設定
    1.で作成したコンテキストをタグ(<コンテキスト名.Provider>)として使用し、子コンポーネントを囲む。
    その際、propsのvalueに子孫コンポーネントへ受け渡したい値を設定する。
  3. コンテキスト値の使用
    子孫コンポーネント側で、useContext(1.のコンテキスト)を行うと、設定した値を取得できる。

useContextの使用例

親コンポーネントで設定した値を、孫コンポーネントで使用する例。
stateとその更新関数も受け渡すため、孫コンポーネントで変更したstateは、リアクティブに親コンポーネントのstateにも反映される。

Parent.tsx
import { Dispatch, SetStateAction, createContext, useState } from 'react';
import { Child } from './Child';

type ISampleValue = {
  title: string;
  value: number;
  setValue: Dispatch<SetStateAction<number>>;
};

// 1. コンテキストを作成(と初期化)し公開する。(別ファイルに切り出した方が良いかも。)
export const SampleContext = createContext<ISampleValue>({
  title: '',
  value: 0,
  setValue: () => {},
});

export function Parent() {
  const [value, setValue] = useState(0);
  // 受け渡す値。propsと同様に、stateの更新関数も受け渡せる。
  // 本来は、useReducerを用いて更新する処理は限定したほうがよい。
  const providValue = {
    title: 'context provider',
    value,
    setValue,
  };

  return (
    // 2. <コンテキスト.Provider>のタグで子コンポーネントを囲む。
    // valueに受け渡す値を設定する。
    <SampleContext.Provider value={providValue}>
      parent component: {providValue.value}
      <Child />
    </SampleContext.Provider>
  );
}

Child.tsx
import { useContext } from 'react';
import { SampleContext } from './Parent';

// 子孫コンポーネントへpropsは渡していない。(バケツリレーしていない)
export function Child() {
  return (
    <>
      <div>child component</div>
      <GrandChild />
    </>
  );
}

export function GrandChild() {
  // 3.useContext(コンテキスト)で、親で設定したコンテキストの値が取得できる。
  // 更新関数を使えば、stateの更新も可能。
  const { title, value, setValue } = useContext(SampleContext);
  return (
    <>
      grand child component: {title}
      <div>
        <input
          type="text"
          value={value}
          // state値を更新→親で表示しているstateにもリアクティブに反映
          onChange={(element) => setValue(+element.target.value)}
        />
      </div>
    </>
  );
}

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