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 による値の受け渡しよりも、ステート管理がすっきりと実装できます。