masalibの日記

システム開発、運用と猫の写真ブログです

React hooksの入門(useContext)

React hooksのuseContextについて勉強した。

バケツリレー(props drilling)問題とは

親=>子供=>孫=>ひ孫のように コンポーネント間でデータを渡すような事があった場合に propsで渡していかないといけない。 このような問題の事をバケツリレー(props drilling)という。

useContextとは

親で設定した内容を

親======>ひ孫

を渡せる機能

図にすると

f:id:masalib:20201114004203p:plain

   ↓

f:id:masalib:20201114004217p:plain

簡単に渡せるようになりバケツリレー問題が解決されます。

useContextの使い方

基本には親のコンポーネントで共有したい変数を設定します。

export const ThemeContext = React.createContext();

exportするのは子供以下のコンポーネントで使うための準備になります。

作ったContextを使用したい範囲を設定します。必ずvalueを設定しなければならないです

contextの設定前

      <div className="App">
        <h1>App(親)</h1>
        親の変数のthemeは{theme}です
        <ChildrenApp />
      </div>

contextの設定後

    <ThemeContext.Provider value={{ theme, setTheme }}>
      <div className="App">
        <h1>App(親)</h1>
        親の変数のthemeは{theme}です
        <ChildrenApp />
      </div>
    </ThemeContext.Provider>

valueはuseStateみたいなfunctionも持たせることができます。

親の方は完了です。

子供以下のコンポーネントで使うためには 親で宣言したcontextをimportします

import { ThemeContext } from "./App";

そして変数として呼びだします

const { theme, setTheme } = useContext(ThemeContext);

あとはどこでも使えます

useContextのサンプル

アタマが悪い私はいつもどおりサンプルを作って学習しました。
親、子、孫のコンポーネントの関係です.

f:id:masalib:20201115025528p:plain

import React, { useState } from "react";
import ChildrenApp from "./ChildrenApp";

export const ThemeContext = React.createContext();

export default function App() {
  console.log("app");
  const [theme, setTheme] = useState("dark");
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <div className="App">
        <h1>App(親)</h1>
        親の変数のthemeは{theme}です
        <ChildrenApp />
      </div>
    </ThemeContext.Provider>
  );
}

子供

import React from "react";
import Grandchild from "./Grandchild";

const ChildrenApp = () => {
  console.log("children");
  return (
    <>
      <div>
        <h2>childrenApptest</h2>
        <Grandchild />
      </div>
    </>
  );
};

export default ChildrenApp;

import React, { useContext } from "react";

//AppコンポーネントからThemeContextをimport
import { ThemeContext } from "./App";

export default function Grandchild() {
  const { theme, setTheme } = useContext(ThemeContext);
  console.log("Grandchild");
  return (
    <>
      <h3>Grandchildtest</h3>
      <div>現在のテーマは{theme}</div>
      <button onClick={() => setTheme("light")}>Lightに変更する</button>
      <button onClick={() => setTheme("dark")}>Darkに変更する</button>
    </>
  );
}

結果

孫のコンポーネントで変更した内容が親のコンポーネントまで反映されています

注意事項

useContextを使用すると、コンポーネントの独立性の多くが失われることに注意することが重要です。このため、useContextに依存するコンポーネントを再利用することはより困難です。

感想

状態管理がかなりめんどくさいかった。親子レベルなら単純にpropsで渡せばいいけど、親=>子供=>孫=>ひ孫までパラメータを渡すのはかなり辛かったのでこの機能は本当にありがたい。

参考URL

https://qiita.com/seira/items/fccdf4e73c59c491558d
https://blog.webdevsimplified.com/2020-06/use-context/
https://blog.logrocket.com/react-reference-guide-context-api/