
コンテキストAPIの基本概念
コンテキストAPIは、Reactが提供する機能で、コンポーネントツリー全体にデータを共有するための方法です。コンテキストを作成し、プロバイダー(Provider)でデータを供給し、コンシューマー(Consumer)またはuseContext
フックでデータにアクセスします。これにより、Propsを何層も介してデータを渡す「Props Drilling」を回避できます。基本的な構造は以下の通りです。
import React, { createContext, useContext } from 'react';
const MyContext = createContext();
function App() {
return (
<MyContext.Provider value="共有データ">
<ChildComponent />
</MyContext.Provider>
);
}
function ChildComponent() {
const value = useContext(MyContext);
return <p>{value}</p>;
}
このコードでは、createContext
でコンテキストを作成し、Provider
で値を供給し、useContext
で値を取得しています。
ハンズオン:テーマ切り替え機能の実装
コンテキストAPIの基本を理解するため、アプリケーション全体のテーマ(例:ライトモードとダークモード)を管理する機能を実装します。第1回で作成したプロジェクト(my-react-app)を使用します。まず、src/ThemeContext.js
を作成してコンテキストを定義します。
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
このコードでは、ThemeContext
を作成し、ThemeProvider
コンポーネントでテーマ状態と切り替え関数を提供します。useTheme
フックでコンテキスト値に簡単にアクセスできます。次に、src/App.js
を以下のように編集してテーマを適用します。
import React from 'react';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import { ThemeProvider, useTheme } from './ThemeContext';
import Home from './Home';
import About from './About';
import './App.css';
function ThemeToggle() {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme}>
{theme === 'light' ? 'ダークモード' : 'ライトモード'}に切り替え
</button>
);
}
function App() {
const { theme } = useTheme();
return (
<div className={`app-container ${theme}`}>
<h1>テーマ切り替えアプリケーション</h1>
<nav>
<Link to="/" style={{ margin: '0 10px' }}>
ホーム
</Link>
<Link to="/about" style={{ margin: '0 10px' }}>
アバウト
</Link>
</nav>
<ThemeToggle />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</div>
);
}
export default function Root() {
return (
<BrowserRouter>
<ThemeProvider>
<App />
</ThemeProvider>
</BrowserRouter>
);
}
このコードでは、ThemeProvider
でアプリケーション全体を囲み、useTheme
フックでテーマにアクセスします。ThemeToggle
コンポーネントでテーマを切り替えます。Home.js
とAbout.js
もテーマを反映するように編集します。src/Home.js
を以下のように変更します(About.js
も同様)。
import React from 'react';
import { useTheme } from './ThemeContext';
function Home() {
const { theme } = useTheme();
return (
<div className={`content ${theme}`}>
<h2>ホーム</h2>
<p>テーマ切り替えをお試しください!</p>
</div>
);
}
export default Home;
src/About.js
も同様に編集します。
import React from 'react';
import { useTheme } from './ThemeContext';
function About() {
const { theme } = useTheme();
return (
<div className={`content ${theme}`}>
<h2>アバウト</h2>
<p>コンテキストAPIでテーマを管理しています。</p>
</div>
);
}
export default About;
src/App.css
にテーマごとのスタイルを追加します。
.app-container {
text-align: center;
padding: 20px;
font-family: Arial, sans-serif;
min-height: 100vh;
}
.app-container.light {
background-color: #ffffff;
color: #000000;
}
.app-container.dark {
background-color: #333333;
color: #ffffff;
}
.content.light {
background-color: #f0f0f0;
padding: 20px;
border-radius: 5px;
}
.content.dark {
background-color: #555555;
padding: 20px;
border-radius: 5px;
}
nav {
margin: 20px 0;
}
nav a {
text-decoration: none;
font-size: 18px;
}
nav a.light {
color: #007bff;
}
nav a.dark {
color: #66b0ff;
}
nav a:hover {
text-decoration: underline;
}
button {
margin: 10px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
開発サーバー(npm start
)が起動している状態で保存すると、ブラウザにナビゲーションとテーマ切り替えボタンが表示されます。「ダークモードに切り替え」をクリックすると、背景色とテキスト色が変化し、ライトモードとダークモードが切り替わります。ホームとアバウトページでもテーマが適用されていることを確認できます。
ハンズオン:コンテキストの拡張
コンテキストAPIの柔軟性を体感するため、読者自身で機能を追加します。以下の課題を試してください。ThemeContext.js
を編集し、テーマに「セピアモード」を追加して、3つのテーマを切り替えられるようにします。以下は一例です。
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prev) => {
if (prev === 'light') return 'dark';
if (prev === 'dark') return 'sepia';
return 'light';
});
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
App.js
のThemeToggle
コンポーネントを以下のように変更します。
function ThemeToggle() {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme}>
{theme === 'light' ? 'ダークモード' : theme === 'dark' ? 'セピアモード' : 'ライトモード'}に切り替え
</button>
);
}
App.css
にセピアモードのスタイルを追加します。
.app-container.sepia {
background-color: #f4ecd8;
color: #5c4b3a;
}
.content.sepia {
background-color: #e6d7b2;
padding: 20px;
border-radius: 5px;
}
nav a.sepia {
color: #8b6f47;
}
ブラウザで確認すると、ボタンをクリックするたびにライト、ダーク、セピアモードが順に切り替わります。自分で新しいテーマ(例:ハイコントラストモード)やコンテキストで管理するデータ(例:ユーザー設定)を追加し、コンテキストAPIの活用方法を試してください。
次のステップに向けて
本記事では、コンテキストAPIを使用してコンポーネント間でデータを共有し、グローバルな状態管理を実現しました。コンテキストAPIは、アプリケーションのスケーラビリティを向上させる重要なツールです。第11回では、カスタムフックを設計し、再利用可能なロジックを作成する方法を学びます。これにより、コードのモジュール性と保守性がさらに向上します。