Reactとは?
ReactはMeta(旧Facebook)が開発したUIライブラリで、宣言的・コンポーネントベース・一度学習すればどこでも書けるという3つの哲学に基づいています。仮想DOMにより高速なUI更新を実現し、JSX/TSXで直感的にUIを記述できます。
プロジェクト作成
Viteで高速な開発環境を構築(推奨)
# Vite + React + TypeScript
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev
# Next.js(フレームワーク)
npx create-next-app@latest
● Vite: 高速ビルド、軽量
● Next.js: SSR/SSG対応、本番向け
関数コンポーネント
// 基本構文
function MyComponent() {
return Hello, React!;
}
// Props型定義(TypeScript)
interface Props {
name: string;
age?: number; // オプショナル
}
function Greeting({ name, age }: Props) {
return (
Hello, {name}!
{age && Age: {age}
}
);
}
● Props: 親から受け取るデータ
● JSX: JavaScript内でHTML風の記述
基本Hooks(useState / useEffect)
useState(状態管理)
// 基本形
const [count, setCount] = useState(0);
const [user, setUser] = useState(null);
// 更新
setCount(count + 1);
setCount(prev => prev + 1); // 推奨
// オブジェクト更新
setUser({ ...user, name: 'New Name' });
関数形式で前の状態を参照すると安全
useEffect(副作用)
// マウント時のみ実行
useEffect(() => {
console.log('Mounted');
}, []);
// 依存配列の値変更時に実行
useEffect(() => {
fetchData(userId);
}, [userId]);
// クリーンアップ
useEffect(() => {
const timer = setInterval(() => {}, 1000);
return () => clearInterval(timer);
}, []);
データ取得、購読、タイマーに使用
その他の重要Hooks
useContext
// Context作成
const ThemeContext = createContext('light');
// Provider
// 使用
const theme = useContext(ThemeContext);
グローバル状態共有
useRef
// DOM参照
const inputRef = useRef(null);
inputRef.current?.focus();
// 値の保持(再レンダーなし)
const countRef = useRef(0);
countRef.current += 1;
return ;
DOM操作・値保持
useMemo / useCallback
// 計算結果をメモ化
const expensiveValue = useMemo(() => {
return heavyCalculation(data);
}, [data]);
// 関数をメモ化
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
パフォーマンス最適化
イベントハンドリング
基本パターン
// クリックイベント
// 引数付き
// フォーム送信
イベント型(TypeScript)
// マウスイベント
const handleClick = (
e: React.MouseEvent
) => { /* ... */ };
// フォームイベント
const handleSubmit = (
e: React.FormEvent
) => {
e.preventDefault();
};
// Changeイベント
const handleChange = (
e: React.ChangeEvent
) => { /* ... */ };
条件付きレンダリング & リスト表示
条件付きレンダリング
// 三項演算子
{isLoggedIn ? : }
// && 演算子
{error && }
// if文(早期return)
if (loading) return ;
if (error) return ;
return ;
リスト表示(map)
// 基本形(key必須)
{users.map(user => (
))}
// インデックスを使う場合
{items.map((item, index) => (
{item}
))}
// フィルタリング
{users
.filter(u => u.active)
.map(u => )
}
key属性は一意な値を指定
フォーム管理
制御されたコンポーネント
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log({ name, email });
};
return (
);
}
React Hook Form(推奨)
import { useForm } from 'react-hook-form';
function Form() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data: any) => {
console.log(data);
};
return (
);
}
高パフォーマンス・バリデーション簡単
データフェッチング
fetch + useEffect
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('/api/users')
.then(res => res.json())
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, []);
if (loading) return Loading...;
if (error) return Error: {error};
return {/* ... */};
}
TanStack Query(推奨)
import { useQuery } from '@tanstack/react-query';
function UserList() {
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then(r => r.json())
});
if (isLoading) return Loading...;
if (error) return Error: {error.message};
return (
{data.map(user => (
))}
);
}
キャッシング・再取得・並列処理が簡単
ルーティング(React Router v6)
import { BrowserRouter, Routes, Route, Link, useNavigate, useParams } from 'react-router-dom';
function App() {
return (
} />
} />
} />
} />
);
}
// パラメータ取得
function UserDetail() {
const { id } = useParams<{ id: string }>();
return User ID: {id};
}
// プログラム的な遷移
function LoginForm() {
const navigate = useNavigate();
const handleLogin = () => {
// ログイン処理後
navigate('/dashboard');
};
return ;
}
パフォーマンス最適化のTips
React.memo
不必要な再レンダーを防ぐ
const MemoComponent = React.memo(MyComponent);
コード分割
遅延読み込みで初回ロード高速化
const LazyComponent = lazy(() => import('./Heavy'));
仮想化
大量リスト表示を高速化
react-window / react-virtualized
key属性
リスト要素の一意性を保証
key={item.id} // 安定した一意なID
TypeScript型定義パターン
Props型定義
// 基本
interface Props {
title: string;
count?: number; // オプショナル
onSubmit: () => void;
}
// children
interface Props {
children: React.ReactNode;
}
// ジェネリック
interface ListProps {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
State型定義
// 基本型
const [count, setCount] = useState(0);
// オブジェクト
interface User {
id: number;
name: string;
}
const [user, setUser] = useState(null);
// 配列
const [users, setUsers] = useState([]);
// Union型
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
実務でよく使うパターン
カスタムHooks
// ローカルストレージ管理
function useLocalStorage(key: string, initialValue: T) {
const [value, setValue] = useState(() => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}
// 使用例
const [theme, setTheme] = useLocalStorage('theme', 'light');
エラーバウンダリ
// クラスコンポーネントが必要
class ErrorBoundary extends React.Component<
{ children: React.ReactNode },
{ hasError: boolean }
> {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
console.error('Error:', error, info);
}
render() {
if (this.state.hasError) {
return エラーが発生しました
;
}
return this.props.children;
}
}
// 使用
よく使うライブラリ
React Router
SPAのルーティング
TanStack Query
データフェッチング・キャッシング
React Hook Form
高パフォーマンスフォーム管理
Zustand / Jotai
軽量グローバル状態管理
Tailwind CSS
ユーティリティファーストCSS
React Native
モバイルアプリ開発
React vs Next.js
React
- UIライブラリ(軽量)
- CSR(クライアントサイドレンダリング)
- ルーティングはライブラリが必要
- 学習コスト低、自由度高
Next.js
- フルスタックフレームワーク
- SSR/SSG/ISR対応
- ファイルベースルーティング内蔵
- SEO最適化、パフォーマンス高
推奨: Reactの基礎を習得後、本番環境ではNext.jsを検討すると良いでしょう。