Blog Article
useContext とは何か?「 グローバルな状態共有 」の意味

はじめに
React でアプリを作っていると、「 この値、いろいろなコンポーネントで使いたい 」という場面に必ず出てきます。ログインユーザーの情報、テーマカラー、言語設定など、画面のあちこちで必要になるデータです。
React は本来、親から子へ props を使って値を渡す仕組みです。しかし、コンポーネントの階層が深くなると、関係のないコンポーネントを何段階も通して値を渡すことになり、コードの見通しが悪くなります。これがいわゆる「 props のバケツリレー 」です。
この問題を解決するための仕組みが useContext です。useContext を理解すると、「 グローバルな状態共有 」という言葉の本当の意味が見えてきます。この記事では、その正体を初学者にもわかるように丁寧に解説します。
参考にしたリンク
https://react.dev/reference/react/useContext
https://react.dev/learn/passing-data-deeply-with-context
“Context lets the parent component make some information available to any component in the tree below it—no matter how deep—without passing it explicitly through props.”
useContext とは何か
useContext を一言で言うなら、 props を使わずに、ツリー全体へ値を配布する仕組み です。
React の「 親から子へ 」というデータの流れを壊さずに、深い階層へ値を届けるための公式な方法です。
例えば、ログインユーザーの情報をヘッダー、サイドバー、メイン画面で使いたい場合を考えます。これらのコンポーネントがツリーの離れた場所にあると、共通の親から何段階も props を渡す必要があります。
中間コンポーネントはその値を使わないのに、ただ渡すだけの役割を持つことになり、責務が曖昧になります。構造が複雑になり、修正や保守が難しくなります。
いつ useContext を使うべきか
- テーマカラー
- 言語設定
- ログインユーザー情報
など、アプリ全体で共通して使う値に適しています。特定の親子関係に依存せず、どこからでも必要になる値です。
Context とは何か
Context は、React が提供する「 値の共有箱 」です。特定の値を Context に入れておくと、その配下にあるどのコンポーネントからでも取り出せます。
const UserContext = createContext(null)<UserContext.Provider value={user}>
<App />
</UserContext.Provider>これで、App 以下のどのコンポーネントからでも user を取得できます。
グローバルな状態共有とはどういう意味か
ここでの「 グローバル 」とは、JavaScript のグローバル変数ではありません。Provider に囲まれた React ツリーの範囲で、どこからでもアクセスできるという意味です。React の管理下にある、安全な共有領域です。
【よくある勘違い】useContext は state を管理していない
非常に多い勘違いがあります。それは「 useContext は state 管理の仕組みである 」という誤解です。
実は、 useContext は state を管理していません。state を運ぶ仕組みなだけです。
次のコードを見てください。
const CounterContext = createContext(null)
function App() {
const [count, setCount] = useState(0)
return (
<CounterContext.Provider value={{ count, setCount }}>
<Counter />
</CounterContext.Provider>
)
}
function Counter() {
const { count, setCount } = useContext(CounterContext)
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
)
}この例で、count を管理しているのは useState です。useContext は、その count と setCount を「 運んでいる 」だけです。
つまり、
- 状態を作るのは
useState - 状態を配るのが
useContext
という役割分担になっています。
state と useContext の役割の違い
項目 | useState | useContext |
|---|---|---|
役割 | 状態を作る | 状態を配る |
管理 | ローカル | 広範囲共有 |
単体で state 管理 | できる | できない |
useContext を使ったグローバルステート管理方法
1. Context を作成する
まずは、共有するための箱を作ります。
import { createContext } from "react"
export const CounterContext = createContext(null)2. state を作成する
次に、実際に管理したい state を useState で作ります。
import { useState } from "react"
const [count, setCount] = useState(0)3. Provider で state を配布する
作成した state を Provider の value に入れて、ツリー全体へ配布します。
<CounterContext.Provider value={{ count, setCount }}>
<App />
</CounterContext.Provider>4. useContext で受け取る
どの階層のコンポーネントからでも、次のように受け取れます。props は不要です。
import { useContext } from "react"
import { CounterContext } from "./CounterContext"
const { count, setCount } = useContext(CounterContext)この 4 手順で、props を使わずにグローバルな state 共有が実現できます。
Zustand とは何か
Zustand (ツー・スタンド)は、React 向けの軽量な状態管理ライブラリです。ドイツ語で「状態(state)」という意味です。
useContext と違い、state の作成、更新、共有を 1 つの仕組みでまとめて扱えます。
useContext では useState と組み合わせる必要がありましたが、Zustand ではストアと呼ばれる場所に state を定義し、どのコンポーネントからでも直接参照と更新ができます。
大きな特徴は、Context を使わなくてもグローバルな state を扱える点です。
じゃあ全部 Zustand で良くない?
一見そう思えますが、必ずしもそうではありません。
useContext は React 標準の仕組みであり、小規模から中規模のアプリで「 値を広く共有したい 」だけの場合には十分です。依存ライブラリも増えません。
一方で、状態が増えてきたり、更新ロジックが複雑になったり、パフォーマンスの最適化が必要になったりすると、Zustand のようなライブラリが力を発揮します。
つまり、
- 単純な共有 →
useContext - 複雑な状態管理 → Zustand
という使い分けが重要です。
具体例で整理する
useContext が適しているケース
- テーマカラー
- 言語設定
- ログインユーザー情報
Zustand が適しているケース
- 多数の state を扱う
- 更新ロジックが複雑
- パフォーマンスを意識する必要がある
まとめ
useContext は、props を使わずにコンポーネントツリー全体へ値を配布する仕組みです。しかし、state を管理する仕組みではありません。state を運ぶための通路です。
ポイント整理
- props のバケツリレーを防ぐ
- アプリ全体で共通の値を扱える
- state を管理しているのは
useState - 複雑になったら Zustand の出番
この違いを理解すると、React の設計が一気にクリアになります。