Blog Article
useContext とは何か?

はじめに
React でアプリを作っていると、「 この値、いろいろなコンポーネントで使いたい 」という場面に必ず出てきます。ログインユーザーの情報、テーマカラー、言語設定など、画面のあちこちで必要になるデータです。
React は本来、親から子へ props を使って値を渡す仕組みです。しかし、コンポーネントの階層が深くなると、関係のないコンポーネントを何段階も通して値を渡すことになり、コードの見通しが悪くなります。これがいわゆる「 props のバケツリレー 」です。
この問題を解決するための仕組みが useContext です。useContext を理解すると、「 グローバルな状態共有 」という言葉の本当の意味が見えてきます。
参考にしたリンク
https://react.dev/reference/react/useContext
https://react.dev/learn/passing-data-deeply-with-context
useContext とは何か
useContext を一言で言うなら、 props を使わずに、ツリー全体へ値を配布する仕組み です。
React の「 親から子へ 」というデータの流れを壊さずに、深い階層へ値を届けるための公式な方法です。
例えば、ログインユーザーの情報をヘッダー、サイドバー、メイン画面で使いたい場合を考えます。これらのコンポーネントがツリーの離れた場所にあると、共通の親から何段階も props を渡す必要があります。
中間コンポーネントはその値を使わないのに、ただ渡すだけの役割を持つことになり、責務が曖昧になります。構造が複雑になり、修正や保守が難しくなります。
useContext は、テーマカラー、言語設定、ログインユーザー情報など、アプリ全体で共通して使う値に適しています。特定の親子関係に依存せず、どこからでも必要になる値です。
Context とは何か
Context は、React が提供する「値の共有箱」です。特定の値を Context に入れておくと、その配下にあるどのコンポーネントからでも取り出せます。
createContext を使って Context を作成
const UserContext = createContext(null)作成した Context にProvider を使って値を渡します。
<UserContext.Provider value={user}>
<App />
</UserContext.Provider>これで、App 以下のどのコンポーネントからでも user を取得できます。
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
という役割分担になっています。
useState と 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 の設計が一気にクリアになります。
理解度チェック
学んだ内容を確認してみましょう。各問題の選択肢から正しい答えを選んでください。
useContext の役割として正しいものはどれですか?
「props のバケツリレー」とは、どのような状態を指しますか?
useState と useContext の役割の組み合わせとして正しいものはどれですか?
useContext を使って Context の値を受け取るとき、何が不要になりますか?