✅ はじめに
こんにちは!このシリーズでは、React + Vite + TypeScript + MUIを使ってモダンなWebアプリを開発する方法をステップバイステップで解説しています。
第5回となる今回は、「React Hook Formを使った複数メールアドレスの入力フォーム」を実装します。useFieldArrayを使用した動的なフォーム要素の追加・削除と、効果的なバリデーション処理を学びます。
📦 使用する技術スタック
| ツール | バージョン | 説明 |
|---|---|---|
| React Hook Form | v7.x | 高性能なフォームバリデーションライブラリ |
| MUI | v5.x | マテリアルデザインベースのUIコンポーネント |
| TypeScript | 5.x | 型安全なJavaScript |
| Vite | 5.x | 高速な開発環境とビルドツール |
🚀 実装手順
1. プロジェクトの作成
まずは、Viteを使って新しいプロジェクトを作成します:
npm create vite@latest react-form-advanced -- --template react-ts cd react-form-advanced npm install
2. 必要なパッケージのインストール
MUIとReact Hook Formをインストールします:
npm install @mui/material @emotion/react @emotion/styled @mui/icons-material react-hook-form @fontsource/roboto
3. 複数メール入力フォームの作成
src/AdvancedForm.tsxを作成します:
import type { FC } from "react"
import { useForm, useFieldArray } from "react-hook-form"
import {
Box,
Button,
Container,
TextField,
Typography,
} from "@mui/material"
import { Add, Delete } from "@mui/icons-material"
type FormValues = {
name: string
emails: { email: string }[]
}
const AdvancedForm: FC = () => {
const {
register,
control,
handleSubmit,
formState: { errors },
} = useForm<FormValues>({
defaultValues: {
name: "",
emails: [{ email: "" }],
},
})
const { fields, append, remove } = useFieldArray({
control,
name: "emails",
})
const onSubmit = (data: FormValues) => {
console.log("送信データ:", data)
alert(JSON.stringify(data, null, 2))
}
return (
<Container maxWidth="sm">
<Box mt={5}>
<Typography variant="h5" gutterBottom>
高度なフォーム(React Hook Form + MUI)
</Typography>
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<Box display="flex" flexDirection="column" gap={2}>
<Box>
<TextField
fullWidth
label="名前"
{...register("name", { required: "名前は必須です" })}
error={Boolean(errors.name)}
helperText={errors.name?.message}
/>
</Box>
{fields.map((field, index) => (
<Box key={field.id}>
<Box display="flex" alignItems="center" gap={1}>
<TextField
fullWidth
label={`メール ${index + 1}`}
{...register(`emails.${index}.email`, {
required: "メールは必須です",
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "メール形式が不正です",
},
})}
error={Boolean(errors.emails?.[index]?.email)}
helperText={errors.emails?.[index]?.email?.message}
/>
<Button
variant="outlined"
color="secondary"
onClick={() => remove(index)}
>
<Delete />
</Button>
</Box>
</Box>
))}
<Box>
<Button
variant="outlined"
startIcon={<Add />}
onClick={() => append({ email: "" })}
>
メール追加
</Button>
</Box>
<Box mt={2} display="flex" justifyContent="center">
<Button type="submit" variant="contained" color="primary">
送信
</Button>
</Box>
</Box>
</form>
</Box>
</Container>
)
}
export default AdvancedForm
4. App.tsxの更新
src/App.tsxを更新してフォームを表示します:
import { ThemeProvider, createTheme } from '@mui/material'
import AdvancedForm from "./AdvancedForm"
import '@fontsource/roboto/300.css'
import '@fontsource/roboto/400.css'
import '@fontsource/roboto/500.css'
import '@fontsource/roboto/700.css'
const theme = createTheme({
typography: {
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
},
})
function App() {
return (
<ThemeProvider theme={theme}>
<AdvancedForm />
</ThemeProvider>
)
}
export default App
🎯 主要なポイント
1. フォーム状態管理
- useForm: フォーム全体の状態とバリデーション管理
- useFieldArray: 動的なフィールド配列の管理
- 型安全な実装: TypeScriptによる型定義
2. バリデーション機能
- 必須チェック: 名前とメールアドレスの入力必須
- メール形式: 正規表現によるメールアドレス形式の検証
- 視覚的フィードバック: エラーメッセージの即時表示
3. UIコンポーネント
- TextField: 入力フィールドとエラー表示の統合
- Button: アイコン付きの操作ボタン
- 動的なUI: フィールドの追加・削除機能
🔚 まとめ
今回は、React Hook Form の useFieldArray を使って、複数メール入力のフォームを実装しました。
動的なフォーム要素の管理とバリデーション処理を効率的に実装できることが分かりました。
📚 次回予告
【第6回】バリデーション結果をモーダルで表示するReact Hook Form実装