0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Reactの状態管理(global state)Context API の使い方

Last updated at Posted at 2025-06-04

Context APIとは

通常のpropsだと親から子から孫と渡さないといけないところをContextを使うと、どこからでも直接使えるようになります。

今回はログイン中のユーザーで説明していきます。全コンポーネントで使い回すための仕組みです。

ex)

  • ヘッダーで「◯◯さん、こんにちは」と表示
  • ログアウトボタンで setLoginUser({ id: 0, name: "",email:""}) として初期化
  • API に loginUser.id を渡してリクエストを送る

使い方(ログイン中のユーザーを使い回す想定)

ここで説明するのは、ログイン中のユーザー情報(id, name,email)をアプリ全体で使いまわす」ための Context APIの実装です。

1.型定義

type/login.ts
export type LoginUserType = {
  id: number;
  name: string;
  email: string;
};

2.Context作成

contexts/LoginUserContext.tsx
import { createContext, useState, ReactNode } from "react";
import { LoginUserType } from "../types/login";

export type LoginUserContextType = {
  loginUser: LoginUserType
  setLoginUser: (user: LoginUserType) => void;
};

export const LoginUserContext = createContext<LoginUserContextType | undefined>(undefined);

export const LoginUserProvider = ({ children }: { children: ReactNode }) => {
  const [loginUser, setLoginUser] = useState<LoginUserType>({
    id: 0,
    name: "",
    email: "",
  });

  return (
    <LoginUserContext.Provider value={{ loginUser, setLoginUser }}>
      {children}
    </LoginUserContext.Provider>
  );
};

3.アプリ全体をProviderで囲む

main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'react-router-dom'
//省略
import { router } from './routes'
import { LoginUserProvider } from "./contexts/LoginUserContext";

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <LoginUserProvider>
      <RouterProvider router={router}/>
    </LoginUserProvider>
  </React.StrictMode>
)

4. どこでも使えるようにする(useContext)

Header.tsx
import { useContext } from "react";
import { LoginUserContext } from "../contexts/LoginUserContext";

export const Header = () => {
  const context = useContext(LoginUserContext);
  if (!context) throw new Error("LoginUserContextが設定されていません");

  const { loginUser } = context;

  return <div>{loginUser.name} さんは({loginUser.email})でログイン中</div>;
};

5.コンテキストを呼び出すファイル(カスタムフック)作成

hooks/useLoginUser.tsx
import { useContext } from 'react'
import { LoginUserContext } from '../contexts/LoginUserContext';

export const useLoginUser = () => {
//LoginUserContext から現在の値を取得。これが undefined の場合=Providerで囲まれていない ということ
  const context = useContext(LoginUserContext);
//エラーを明示的に投げて、開発者に「Providerで囲んでないよ!」と気づかせる。これがあることで安全なコードになる
  if(context === undefined) {
    throw new Error('useLoginUser must be used within a LoginUserProvider');
  }
  return context; //context(つまり { loginUser, setLoginUser })を返す。呼び出し元でこれを使えば、ログインユーザー情報に簡単にアクセス可能
}

6. どこでも使えるようにする(useContext)

例:Header コンポーネントなどで

components/Header.tsx
import { useLoginUser } from "../hooks/useLoginUser";

const Header = () => {
  const { loginUser } = useLoginUser();

  return (
    <header className="p-4 bg-gray-100">
      <p>{loginUser.name} さん({loginUser.email})でログイン中</p>
    </header>
  );
};

export default Header;

その他状態管理

Redux

学習コストが高い😅

Zustand

軽量な使いやすい状態管理ライブラリでReduxの代替になります。

Recoil

Recoilの開発は終了しました。

状態管理を最適化したい

ContextAPIなどを使っていると一見良さそうですが、パフォーマスが下がってしまったりします。コードが肥大化してしまい処理が複雑になってしまったりします。
そこでグローバル管理を最低限にするのがいいです。
必要なのがTanStackQuery(旧React Query)です。

参考資料

  • ChatGPT

  • HapinessChainの無料特典

ゆうだい@プログラミングで月100万

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?