React のカスタムフックを活用して、状態管理、バリデーション、アクセシビリティ対応を含む包括的なフォームシステムを構築し、モダンな React 開発の実践的なスキルを学習します。
- React カスタムフックの設計と実装
- TypeScript を活用した型安全なフォーム開発
- リアルタイムバリデーションの実装
- アクセシビリティ対応のベストプラクティス
- React Testing Library を使用したテスト手法
再利用可能でアクセシブルなフォームコンポーネントライブラリを作成します。カスタムフック useForm を中心に、実務で即座に活用できる高品質なフォームシステムを実装し、React の高度な機能を習得します。
- Node.js 18.0 以上
- npm または yarn
- React の基本知識
- TypeScript の基本文法
- HTML/CSS の基礎知識
# 1. ディレクトリに移動
cd repos/10
# 2. 依存関係のインストール
npm install
# 3. 開発サーバーの起動
npm run dev
# 4. ブラウザでアクセス
# http://localhost:3000
# 5. テストの実行
npm test
# 6. テストUIでデバッグ
npm run test:ui
/
├── src/ # ソースコード
│ ├── components/ # Reactコンポーネント
│ │ ├── ContactForm.tsx # メインフォーム例
│ │ ├── InputField.tsx # 入力フィールド
│ │ ├── SelectField.tsx # セレクトフィールド
│ │ ├── CheckboxField.tsx # チェックボックス
│ │ ├── RadioGroup.tsx # ラジオグループ
│ │ └── __tests__/ # コンポーネントテスト
│ ├── hooks/ # カスタムフック
│ │ ├── useForm.ts # メインフォームフック
│ │ └── __tests__/ # フックテスト
│ ├── types/ # 型定義
│ │ └── form.ts # フォーム関連の型
│ ├── styles/ # スタイルシート
│ │ └── global.css # グローバルCSS
│ ├── test/ # テスト設定
│ │ └── setup.ts # Vitest設定
│ ├── App.tsx # メインアプリ
│ └── main.tsx # エントリーポイント
├── tests/ # E2Eテスト
├── dist/ # ビルド成果物
├── package.json # パッケージ設定
├── tsconfig.json # TypeScript設定
├── vite.config.ts # Vite設定
├── vitest.config.ts # Vitest設定
└── README.md # このファイル
型安全なフォーム状態管理を行うカスタムフックを作成します。
// src/hooks/useForm.ts
import { useState, useCallback } from 'react';
interface UseFormOptions<T> {
initialValues: T;
validationRules?: ValidationRules<T>;
onSubmit: (values: T) => void | Promise<void>;
}
export function useForm<T extends Record<string, any>>({
initialValues,
validationRules,
onSubmit,
}: UseFormOptions<T>) {
const [values, setValues] = useState<T>(initialValues);
const [errors, setErrors] = useState<Partial<Record<keyof T, string>>>({});
const [touched, setTouched] = useState<Partial<Record<keyof T, boolean>>>({});
// バリデーションロジック
const validate = useCallback(() => {
// 実装
}, [values, validationRules]);
// フォームの状態とハンドラを返す
return {
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
resetForm,
};
}
再利用可能なフォームコンポーネントを実装します。
// src/components/InputField.tsx
import React from 'react';
interface InputFieldProps {
label: string;
name: string;
type?: 'text' | 'email' | 'password' | 'tel' | 'number';
value: string;
error?: string;
touched?: boolean;
required?: boolean;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
onBlur: () => void;
}
export const InputField: React.FC<InputFieldProps> = ({
label,
name,
type = 'text',
value,
error,
touched,
required,
onChange,
onBlur,
}) => {
const showError = touched && error;
return (
<div className='input-field'>
<label htmlFor={name} className='input-field__label'>
{label}
{required && <span className='input-field__required'>*</span>}
</label>
<input
id={name}
name={name}
type={type}
value={value}
onChange={onChange}
onBlur={onBlur}
className={`input-field__input ${showError ? 'input-field__input--error' : ''}`}
aria-invalid={showError}
aria-describedby={showError ? `${name}-error` : undefined}
/>
{showError && (
<span id={`${name}-error`} className='input-field__error' role='alert'>
{error}
</span>
)}
</div>
);
};
ARIA 属性やキーボードナビゲーションを実装し、すべてのユーザーが使いやすいフォームを作成します。
- useForm カスタムフックの実装
- TypeScript による型安全なフォーム状態管理
- バリデーション機能(必須、文字数、パターン等)
- エラーハンドリングと表示
- 再利用可能なフォームコンポーネント
- アクセシビリティ対応(ARIA 属性、キーボード操作)
- 包括的な単体テスト(カバレッジ 80%以上)
- 統合テストの実装
- パフォーマンス最適化(メモ化、デバウンス)
- カスタマイズ可能なスタイルシステム
- フォーム状態の保存(localStorage)
- 動的フォームフィールドの追加/削除
- 多言語対応(i18n)
項目 | 配点 | 評価内容 |
---|---|---|
機能性 | 40 点 | useForm フックとコンポーネントの実装 |
型安全性 | 30 点 | TypeScript の活用と型推論 |
アクセシビリティ | 20 点 | ARIA 属性、キーボード対応 |
テスト | 10 点 | カバレッジとテスト品質 |
問題: ルール定義が不正 解決方法:
// 間違い: 文字列ではなくRegExpを使用
validationRules: {
email: {
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // 正しいRegExp
}
}
問題: 型定義と初期値が一致しない 解決方法:
- ジェネリクスの型定義を正確に指定
- 初期値のプロパティをすべて含める
tsconfig.json
の strict モードを確認
問題: DOM 要素が見つからない 解決方法:
# テストUIでデバッグ
npm run test:ui
# ロール名で要素を取得
const input = screen.getByRole('textbox', { name: /email/i });
- React 公式ドキュメント - Hooks
- TypeScript Handbook
- Testing Library Documentation
- WAI-ARIA Authoring Practices
- MDN - アクセシビリティ
- このリポジトリをフォーク
submission/[あなたの名前]
ブランチを作成- React フォームシステムを実装
- プルリクエストを作成
- 自動採点の結果を確認
- 必要に応じて修正
# GitHub で Fork ボタンをクリック後
git clone https://github.com/[あなたのユーザー名]/exercise-react.git
cd exercise-react
git checkout -b submission/taro-yamada
# useFormフックの実装
git add src/hooks/useForm.ts
git commit -m "feat: 型安全なuseFormカスタムフックを実装"
# フォームコンポーネントの作成
git add src/components/
git commit -m "feat: 再利用可能なフォームコンポーネントを作成"
# アクセシビリティ対応
git add src/components/
git commit -m "a11y: ARIA属性とキーボードナビゲーションを実装"
# テストの追加
git add src/**/__tests__/
git commit -m "test: カスタムフックとコンポーネントのテストを追加"
git push origin submission/taro-yamada
GitHub でプルリクエストを作成:
- タイトル:
[提出] 演習10: Reactフォーム - 山田太郎
- 本文: 実装した機能とアクセシビリティ対応を記載
- 状態管理ロジックの分離
- ジェネリクスによる型安全性
- パフォーマンスを考慮した実装
- すべてのフォーム要素に ID とラベルを関連付け
- エラーメッセージに aria-live を設定
- キーボードのみでの操作を保証
// ユーザー目線でのテスト
const user = userEvent.setup();
const input = screen.getByLabelText('メールアドレス');
await user.type(input, 'test@example.com');
頑張ってアクセシブルで使いやすいフォームを作成してください!