Reactエコシステムの準備
Reactアプリケーションを開発する際、以下のツール群が広く利用されています。
- React公式ドキュメント(日本語): コアフレームワークの学習に最適
- React Router: ページ遷移やルーティング機能を提供
- Zustand: 軽量な状態管理ライブラリ
- TanStack Query: 非同期データ取得とキャッシュ管理
- Vite: 高速ビルドとホットリロードを実現するモダンなビルドツール
- Ant Design / FontAwesome: UI部品やアイコンの提供
プロジェクトの初期化
まずViteを使用して新しいReactプロジェクトを作成します。
npm create vite@latest my-react-app --template react
cd my-react-app
npm install
npm run dev
この手順により、JSX変換、モジュールバンドリング、開発サーバーが即座に利用可能になります。
仮想DOMの理解
Reactはレンダリングプロセスにおいて「仮想DOM」を中核としています。これは実際のブラウザDOMの軽量なJavaScriptオブジェクト表現です。
- 変更の差分を効率的に計算し、最小限の再描画を行う
- パフォーマンス向上と一貫したUI更新を実現
- 開発者は直接DOM操作を行わず、状態に基づいてビューを宣言的に記述
JSX構文のルール
JSXはHTMLに似た構文で、JavaScriptの中に埋め込むことができます。主な規則:
- 属性名は
className、htmlForのようにキャメルケースで記述 - インラインスタイルは
style={{ fontSize: '16px' }}のようなオブジェクト形式 - 式の挿入には
{}を使用(例:{user.name}) - ルート要素は単一のタグで囲む必要がある
- 自己終了タグは常に
/>で閉じる(例:<img />)
関数型コンポーネントと状態管理
現代のReactでは関数型コンポーネントが主流です。Hooksを用いることでクラスコンポーネントと同等の機能を実現できます。
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const [name, setName] = useState('Default');
const increment = () => {
// 正確な値を保証するため、関数形式で更新
setCount(prev => prev + 1);
};
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={increment}>+1</button>
<p>名前: {name}</p>
</div>
);
}
副作用の管理: useEffect
useEffectはコンポーネントのマウント・更新・アンマウント時に処理を実行するためのフックです。
import { useEffect, useState } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
// 初期読み込み時のみ実行(依存配列を空に)
fetch('/api/data')
.then(res => res.json())
.then(setData);
// クリーンアップ関数(オプション)
return () => {
console.log('コンポーネントがアンマウントされました');
};
}, []); // 空の依存配列=初回レンダリング時のみ
return <div>{data ? data.message : '読み込み中...' }</div>;
}
パフォーマンス最適化手法
不要な再レンダリングを防ぐために以下の方法があります。
React.memo
親コンポーネントの状態変更でも、子コンポーネントのpropsが変わっていなければ再レンダリングをスキップします。
const MemoizedChild = React.memo(function Child({ name }) {
console.log('子コンポーネントがレンダリングされました');
return <div>こんにちは、{name}さん!</div>;
});
useCallback
関数の参照を安定させることで、その関数をpropsに受け取る子コンポーネントの不要な再レンダリングを防ぎます。
function Parent() {
const [value, setValue] = useState('');
// 参照が維持されるように関数をラップ
const handleChange = useCallback((e) => {
setValue(e.target.value);
}, []);
return <MemoizedChild onChange={handleChange} />;
}
useMemo
高コストな計算結果をキャッシュし、依存値が変更されたときだけ再計算します。
function ExpensiveComponent({ list, filter }) {
const filteredList = useMemo(() => {
return list.filter(item => item.includes(filter));
}, [list, filter]); // listまたはfilterが変更されたときのみ再実行
return <ul>{filteredList.map(...)}</ul>;
}
コンテキストによる状態共有
深いネストでのprops渡しを避けるために、Context APIを使用できます。
import { createContext, useContext } from 'react';
const ThemeContext = createContext();
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext);
return <div className={theme}>現在のテーマ: {theme}</div>;
}
遅延読み込み (Lazy Loading)
コード分割と動的読み込みにより、初期ロード時間を短縮できます。
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback=<div>読み込み中...</div>>
<HeavyComponent />
</Suspense>
);
}
スタイリング戦略
Reactアプリケーションでは複数のスタイリングアプローチが存在します。
- CSS Modules:
filename.module.cssで作成し、自動的にスコープが隔離 - Styled-components: JavaScript内にCSSを記述、動的プロパティ対応
- Utility-first CSS (Tailwind): 小さなクラスを組み合わせてデザイン
一般的には、インラインスタイルは動的スタイルに限定し、静的スタイルは外部CSSファイルで管理することが推奨されます。