React: createContext と useState によるステート管理(サンプルあり)

スポンサーリンク

React コンテキストを利用して、アプリケーション全体でステートを管理する方法を紹介します。コンテキストの作成は createContext メソッドで行い、コンテキストの取得は useContext メソッドで行います。

今回は、子コンポーネントのボタンクリックでコンテキストを更新し、親コンポーネントでコンテキストの値をバインドしています。

動作イメージ

createContext(AppState.ts)

createContext フックを使って、コンテキストオブジェクト menuContext を作成します。このコンテキストオブジェクトには、boolean 型の isOpen プロパティと、isOpen プロパティを切り替える setOpen メソッドが含まれます。

import { createContext } from "react";

export const menuContext = createContext({
  isOpened: false,
  setOpened: (isOpen: boolean) => {}
});

useContext(Menu.tsx)

useContext フックを呼び出し、menuContext オブジェクトを引き込みます。ボタンクリック時に呼び出す、toggleOpen メソッドの中で isOpen プロパティの値を切り替えています。

import React, { useContext } from "react";
import { menuContext } from "../contexts/AppState";

export const Menu = () => {
  // AppState.ts の menuContext を引数に与える
  const { isOpened, setOpened } = useContext(menuContext);
  
  // menuContext の isOpened プロパティを切り替える
  const toggleOpen = () => setOpened(!isOpened);
  
  return (
    <div style={{ border: "1px solid gray", margin: "1rem", padding: "1rem" }}>
      <div>Menu.tsx</div>

      {/* menuContext の setOpened メソッドを呼び出す */}
      <button onClick={toggleOpen}>メニューの開閉</button>
    </div>
  );
};

useState(App.tsx)

Menu.tsx で切り替えられる isOpened の値を、Menu.tsx の親である App.tsx で参照します。

function App() {
  // AppState.menuContext に対応するプロパティを useState で用意する
  const [isOpened, setOpened] = useState(false);

  return (
    <div style={{ border: "1px solid gray", margin: "1rem", padding: "1rem" }}>
      <div>App.tsx</div>

      {/* Provider 経由でステートをバインドする */}
      <menuContext.Provider value={{ isOpened, setOpened }}>
        <div>
          {/* 子コンポーネント(Menu.tsx)で切り替えた isOpened ステートをバインドする */}
          メニュー {isOpened ? "表示" : "非表示"}
        </div>
        <Menu />
      </menuContext.Provider>
    </div>
  );
}

今回は、React コンテキストに夜、アプリケーションステートの管理方法を紹介しました。props による値の受け渡しよりも、ステート管理がすっきりと実装できます。

サンプルアプリケーション

参考情報

コンテクスト – React
ユーザインターフェース構築のための JavaScript ライブラリ
フック API リファレンス – React
ユーザインターフェース構築のための JavaScript ライブラリ

コメント

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