const value = useContext(SomeContext)
interface ThemeContextType {
theme: 'light' | 'dark';
toggle: () => void;
}
const ThemeContext = createContext<ThemeContextType | null>(null);
// null チェックを避けるカスタムフック
const useTheme = () => {
const ctx = useContext(ThemeContext);
if (!ctx) throw new Error('ThemeProviderが必要です');
return ctx;
};import { createContext, useContext, useState } from 'react';
// ── Step 1: Context を作る(初期値を設定)────────────────
type Theme = 'light' | 'dark';
type ThemeContextType = {
theme: Theme;
toggle: () => void; // テーマを切り替える関数
};
// createContext で Context を作成
const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggle: () => {},
});
// ── Step 2: Provider でアプリを囲む(値を提供する側)───
function App() {
const [theme, setTheme] = useState<Theme>('light');
const toggle = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
// value に渡したオブジェクトが全子コンポーネントで使える
<ThemeContext.Provider value={{ theme, toggle }}>
<Header /> {/* どこからでも theme にアクセス可能 */}
<MainContent />
<Footer />
</ThemeContext.Provider>
);
}
// ── Step 3: 深い子コンポーネントで useContext を使う ─────
// props でバケツリレーしなくてもOK!
function DarkModeButton() {
const { theme, toggle } = useContext(ThemeContext);
return (
<button onClick={toggle}>
現在: {theme === 'light' ? '☀️ ライト' : '🌙 ダーク'}
</button>
);
}Contextが更新されると、その値を使っているすべてのコンポーネントが再レンダーされる。頻繁に変わる値は別Contextに分離するか、useReducerと組み合わせる。