🐕
【TypeScript + Next.js】 Context Provider を作ってみよう
Providerとは
- React の Context API で使われるコンポーネント
- データ(状態)をコンポーネントツリー全体に「供給(provide)」する役割
-
useContextとセットで使い、props drilling(深い階層への props 渡し)を解消できる
例:
<MyContext.Provider value={someValue}>
<Child />
</MyContext.Provider>
基本構造
-
Context 作成
const MyContext = createContext(initialValue); -
Provider で囲む
<MyContext.Provider value={someValue}> <App /> </MyContext.Provider> -
子コンポーネントで利用
const value = useContext(MyContext);
よく使うパターン
-
認証情報 (AuthProvider)
→ ログイン状態やユーザー情報を全体で共有 -
テーマ管理 (ThemeProvider)
→ ダークモード / ライトモードの切り替え -
状態管理ライブラリと組み合わせ
→ Redux の<Provider>や React Query の<QueryClientProvider>
📌 UserContext の例
1. Context 定義
// contexts/UserContext.tsx
"use client";
import { createContext, useContext, useState, ReactNode } from "react";
type User = {
id: string;
name: string;
email: string;
} | null;
type UserContextType = {
user: User;
setUser: (user: User) => void;
};
// Context の作成
const UserContext = createContext<UserContextType | undefined>(undefined);
// Provider コンポーネント
export function UserProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User>(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
}
// ✅ より使いやすくするためのカスタムフック
export function useUser() {
const context = useContext(UserContext);
if (!context) {
throw new Error("useUser は UserProvider 内で使用してください");
}
return context;
}
2. アプリ全体を Provider でラップ
// app/layout.tsx (Next.js 13+)
import { UserProvider } from "@/contexts/UserContext";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ja">
<body>
<UserProvider>
{children}
</UserProvider>
</body>
</html>
);
}
3. コンポーネントで利用
// app/page.tsx
"use client";
import { useUser } from "@/contexts/UserContext";
export default function HomePage() {
const { user, setUser } = useUser();
return (
<main>
{user ? (
<>
<h1>こんにちは、{user.name} さん 👋</h1>
<button onClick={() => setUser(null)}>ログアウト</button>
</>
) : (
<>
<h1>ログインしてください</h1>
<button
onClick={() =>
setUser({ id: "1", name: "ヒョニ", email: "hyoni@example.com" })
}
>
ログイン
</button>
</>
)}
</main>
);
}
✅ 動作の流れ
-
UserProviderがアプリ全体でuser状態を管理 -
useUser()を使うと、どのコンポーネントからでもユーザー情報にアクセス可能 -
HomePageのようなコンポーネントでは props を渡さなくても直接利用できる
知っておくべきこと
-
Provider はネストできる
複数の Context を同時に使える -
value が変わると子コンポーネントが再レンダーされる → パフォーマンス注意
-
カスタムフックと組み合わせると便利
const useAuth = () => useContext(AuthContext); -
必要以上に多用しない
状態がローカルで済む場合は useState で十分
Discussion