気まぐれ更新

なんとく知っていた Context API を理解する

なんとなく知っていたこと

  • props として渡さなくても上位コンポーネントのデータにアクセスできる
  • prop drilling を避けれる
  • react-redux のProvider の Pure React版

説明

Context API は 簡単にまとめると createContext 関数を介して生成した Context をその Context 自身が持つ
Provider という React Component で データを共有したいコンポーネント群をラップすることで
どこの階層のコンポーネントからもデータにアクセスできるような仕組みのことです

これにより、下記のように 子コンポーネントでは使用しないが孫コンポーネントで使用するためだけに
props を受け渡すようなケース(props drilling)を回避できます
(今回の例はすごくシンプルなので問題になりませんが、規模や階層が増えてくるとカオスになります)

親->(props1)->子->(props1)->孫

それでは上記の例を実際にコードに起こしてみようと思います

Context API を使用しない場合

import React from 'react';

const Parent = () => {
  return (
    <Child text="for grandchild" />
  );
};

// Child は受け取ってGrandChildに渡すだけ
const Child = ({ text }) => {
  return (
    <GrandChild text={text} />
  );
};

const GrandChild = ({ text }) => {
  return (
    <p>{text}</p>
  );
};

export default Parent;

Context API を使用する場合

import React from 'react';

const TextContext = React.createContext()

const Parent = () => {
  return (
    <TextContext.Provider value="for grandchild">
      <Child />
    </TextContext.Provider>
  );
};

const Child = ({ text }) => {
  return (
    <GrandChild />
  );
};

const GrandChild = ({ text }) => {
  return (
    <TextContext.Consumer>
      {(text) => <p>{text}</p>}
    </TextContext.Consumer>
  );
};

export default Parent;

このように createContext 経由で生成した context の Provider と Consumer を駆使することにより
props を経由せずにデータの受け渡しができます

Context の使い所

  • 一連のコンポーネント群の大部分で使用するようなデータがあるとき(テーマ情報など)
  • Atomic Design を採用している場合(props drilling の回避)

pros/cons

pros

  • props drilling を回避できる

cons

  • 多用しすぎるとデータフローが分かりづらくなる可能性あり

思うこと

すでにprops drilling 状態になっているものに対しても導入が楽そう
Redux の代用になるのでは?!みたいな記事がわりと出てるけど、そもそもコンセプトが違うので個人的にはそれはなしだと思ってる
(工夫次第でそれっぽいものはできそう)