【React】useContextにて他のコンポーネントからContextに値をセットする方法

React
 

環境

  • npm 8.6.0
  • React 17.0.2

初めに

本記事では題名の通り、useContextにて宣言された変数の値を他のコンポーネントから再度定義する方法について紹介します。

その前に簡単ではありますが、useContextについて触れておきます。

そんなのわかっているよ!!!早く解決方法を!!!

という方は「解決方法」までスキップしてください。

useContextとは

簡単な使用例

app.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import ComponentA from "./components/ComponentA";

export const ThemeContext = React.createContext();

function App() {
  const [theme, setTheme] = useState("indexから定義しています!");
  return (
    <ThemeContext.Provider value={{ theme }}>
      <ComponentA />
    </ThemeContext.Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

ComponentA.js

import { useContext } from "react";
import { ThemeContext } from "../index";

const ComponentA = () => {
  const { theme } = useContext(ThemeContext);
  return <div>{theme}</div>;
};

export default ComponentA;

出力される画面の様子

出力されるブラウザの様子

こちらの使用方法ですが、親コンポーネントにて定義された値を取得して子コンポーネントにて表示していますが、子コンポーネントからその値を更新したいと状況ってあると思います。

そちらの方法を紹介していきます。

解決方法

親コンポーネントのStateにて定義されている値とそのセッター関数のどちらもProviderのValueに渡し、子コンポーネントにてセッター関数を呼び出すことでContextで定義された値を変更することが可能になります。

イメージとしてはstateに定義されている値に加えて、そのセッター関数もContext(→つまり、グローバル変数)として用意してあげることで、どのコンポーネントからでも使えるようにした、ということです。

app.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import ComponentA from "./components/ComponentA";

export const ThemeContext = React.createContext();

function App() {
  const [theme, setTheme] = useState("indexから定義しています!");
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <ComponentA />
    </ThemeContext.Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

ComponentA.js

import { useContext } from "react";
import { ThemeContext } from "../index";

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

  const clickHandler = () => {
    setTheme("子コンポーネントからContextに値をセットすることも可能です!");
  };

  return (
    <div>
      <p>{theme}</p>
      <button onClick={clickHandler}>押すとコメントが変わります</button>
    </div>
  );
};

export default ComponentA;

出力される画面の様子

上記の画面にてボタンを押下すると次のように遷移します。

ボタン押下後の画面の様子

ボタン押下により、何が起きているかをステップに分けて説明していきます。

  1. ボタン押下によりbuttonタグのonClickメソッドが起動します。
  2. そのonClickにて宣言されているclickHandlerにて記載されているsetThemeメソッドが起動します。
  3. setThemeメソッドはuseStateにて定義されたThemeの値を変えるメソッドなので、Themeの値が更新されます。
  4. stateが更新されたことでコンポーネントが再レンダーされ、子コンポーネントの値が現在のThemeの値に書き換わるという訳です。

コード記述に関しての注意書き

私を2日間も苦しめた内容を共有します。

親コンポーネントにて定義されているStateの命名は子コンポーネントで必ず同じものでなければなりません。

つまり

親コンポーネントにて定義されている

const [theme, setTheme]

子コンポーネントにて定義されている

const { theme, setTheme }

これらの命名は同じでなければならないということです。

同じでないとundefiedが返ってきます。

useContextにてContextへ値をセットする - Codesandbox
useContextにてContextへ値をセットする using react, react-dom, react-scripts

終わり

コメント

タイトルとURLをコピーしました