目次
- Context とは?
- useContext の基本的な使い方
- useContext を使うメリット
- 実践例
- useContext の注意点
- まとめ
Contextとは?
ReactのContextは、ツリー状のコンポーネント全体でデータを共有する仕組みです。
通常、Reactではpropsを使ってデータを親コンポーネントから子コンポーネントに渡しますが、Contextを使うとどの階層にあるコンポーネントでも直接データを取得 できます。
Context の主な特徴
- データの「グローバルな状態管理」が簡単になる
- 子コンポーネントでpropsを繰り返し渡す必要がなくなる
- 状態やテーマ設定、認証情報などをコンポーネント全体で共有しやすい
useContextの基本的な使い方
1. Contextを作成
以下に、テーマを切り替えるためのThemaContextを作成し、使用する例を示します。
import React, { createContext, useState, useContext } from "react";
// Context を作成
const ThemeContext = createContext();
2. Context を提供 (Provider)
ThemeProvider Componentは、ThemeContext.Provider を使ってContextの値を設定し、提供します。
このContextは、テーマに関するデータ(theme)と、テーマを切り替える関数(toggleTheme)を持ちます。
function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
// テーマを切り替える関数
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};
// Context に渡す値を指定
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
childrenをラップすることで、どのComponentでもContextの値にアクセスできるようになります。
3. Contextを消費 (UseContext)
useContextフックを使うことで、Contextの値を直接取得します。
function ThemeSwitcher() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div style={{ background: theme === "light" ? "#fff" : "#333", color: theme === "light" ? "#000" : "#fff" }}>
<p>現在のテーマ: {theme}</p>
<button onClick={toggleTheme}>テーマを切り替え</button>
</div>
);
}
4. アプリ全体で使用する
function App() {
return (
<ThemeProvider>
<ThemeSwitcher />
</ThemeProvider>
);
}
export default App;
useContextを使うメリット
1. props を繰り返し渡す必要がない
子や孫コンポーネントにデータを渡すとき、親から順番にpropsを伝播させる必要がなくなる
2. コードがシンプルに
useContext を使うと、直接必要な値を取得できるため、コードが簡潔になる
3. グローバルな状態管理
コンポーネント間で共通のデータ(例: ユーザー情報、テーマ設定など)を管理しやすい
実践例
ここでは、カートのアイテム数を Context で管理する例を紹介します。
Contextの作成
import React, { createContext, useState, useContext } from "react";
// カートの Context を作成
const CartContext = createContext();
Providerの作成
function CartProvider({ children }) {
const [cartItems, setCartItems] = useState([]);
// アイテムを追加する関数
const addToCart = (item) => {
setCartItems([...cartItems, item]);
};
return (
<CartContext.Provider value={{ cartItems, addToCart }}>
{children}
</CartContext.Provider>
);
}
カートを表示するコンポーネントでContextを使う
function Cart() {
const { cartItems } = useContext(CartContext);
return (
<div>
<h2>カートの中身:</h2>
<ul>
{cartItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
アイテムをカートに追加するコンポーネントでContextを使う
function AddItemButton({ item }) {
const { addToCart } = useContext(CartContext);
return <button onClick={() => addToCart(item)}>「{item}」をカートに追加</button>;
}
全体をラップする
function App() {
return (
<CartProvider>
<AddItemButton item="りんご" />
<AddItemButton item="オレンジ" />
<Cart />
</CartProvider>
);
}
export default App;
useContextの注意点
1. 大規模アプリでは複雑化しやすい
- 複数のContextを作成する場合、それぞれのProviderでラップする必要があり、コードが見づらくなることがあります。
- ReduxやZustandなどの状態管理ライブラリを使うことも検討しましょう。
2. 不要な再レンダリングに注意
- Contextに依存するすべてのコンポーネントが、値の変更時に再レンダリングされます。
- 性能が気になる場合は、値を分割するか、React.memo を活用するのが良いです。
3. 依存関係の管理が重要
- Contextの値を変更する処理が複雑になると、管理が難しくなることがあります。
まとめ
- useContext は React の Context を簡単に使うためのフックで、グローバルなデータ共有に役立つ
- 手順
- createContext で Context を作成
- Provider を使って値を渡す
- 子コンポーネントで useContext を呼び出して値を取得・操作する
- テーマ管理、認証情報、カート機能など、複数のコンポーネントで同じデータを使う場合に便利
- ただし、大規模アプリではReduxなどの状態管理ライブラリを使うことも検討すると良い