✅ はじめに
こんにちは!このシリーズでは、React + Vite + TypeScript + MUIを使ってモダンなWebアプリを開発する方法をステップバイステップで解説しています。
第6回となる今回は、「バリデーション結果をモーダルで表示するReact Hook Form実装」に取り組みます。前回作成したフォームをベースに、バリデーションエラーや送信内容の確認結果をモーダル(ダイアログ)で表示するUIを実装していきます。
📦 使用する技術スタック
| ツール | バージョン | 説明 |
|---|---|---|
| React Hook Form | v7.x | 高性能なフォームバリデーションライブラリ |
| MUI | v5.x | マテリアルデザインベースのUIコンポーネント |
| TypeScript | 5.x | 型安全なJavaScript |
| Vite | 5.x | 高速な開発環境とビルドツール |
🚀 実装手順
1. プロジェクトの作成
まずは、Viteを使って新しいプロジェクトを作成します:
npm create vite@latest react-form-modal -- --template react-ts cd react-form-modal 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/FormWithModal.tsxを作成します:
import { useForm } from "react-hook-form"
import {
Box,
Button,
Container,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Typography,
} from "@mui/material"
import { useState } from "react"
type FormValues = {
name: string
email: string
}
export default function FormWithModal() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormValues>({
defaultValues: {
name: "",
email: "",
},
})
const [open, setOpen] = useState(false)
const [submittedData, setSubmittedData] = useState<FormValues | null>(null)
const onSubmit = (data: FormValues) => {
setSubmittedData(data)
setOpen(true)
}
return (
<Container maxWidth="sm">
<Box mt={5}>
<Typography variant="h5" gutterBottom>
モーダル表示付きフォーム
</Typography>
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<Box display="flex" flexDirection="column" gap={2}>
<TextField
label="名前"
fullWidth
{...register("name", { required: "名前は必須です" })}
error={Boolean(errors.name)}
helperText={errors.name?.message}
/>
<TextField
label="メール"
fullWidth
{...register("email", {
required: "メールは必須です",
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "メール形式が不正です",
},
})}
error={Boolean(errors.email)}
helperText={errors.email?.message}
/>
<Button type="submit" variant="contained" color="primary">
送信
</Button>
</Box>
</form>
</Box>
<Dialog open={open} onClose={() => setOpen(false)}>
<DialogTitle>送信内容の確認</DialogTitle>
<DialogContent dividers>
{submittedData && (
<Box>
<Typography>名前: {submittedData.name}</Typography>
<Typography>メール: {submittedData.email}</Typography>
</Box>
)}
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)} color="primary">
閉じる
</Button>
</DialogActions>
</Dialog>
</Container>
)
}
4. App.tsxの更新
最後に、src/App.tsxを更新してフォームを表示します:
import { ThemeProvider, createTheme } from '@mui/material'
import FormWithModal from "./FormWithModal"
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}>
<FormWithModal />
</ThemeProvider>
)
}
export default App
🎯 主要なポイント
1. モーダル管理
- Dialog コンポーネント: MUIのモーダルダイアログを使用
- 状態管理: useStateでモーダルの開閉を制御
- 送信データ: 確認用モーダルに表示するデータを保持
2. フォーム機能
- バリデーション: 名前とメールアドレスの入力検証
- エラー表示: フィールド単位でのエラーメッセージ表示
- 送信処理: フォームデータをモーダルで確認
3. UIコンポーネント
- Dialog関連: タイトル、コンテンツ、アクションの3層構造
- TextField: エラー状態とメッセージの統合
- レイアウト: Boxコンポーネントによる柔軟な配置
🔚 まとめ
今回は、React Hook FormとMUIのDialogコンポーネントを組み合わせて、ユーザーフレンドリーなフォームを実装しました。バリデーション結果や送信内容をモーダルで表示することで、より分かりやすいUIを実現できました。
📚 次回予告
【第7回】React Hook Form × MUI:フォームをコンポーネント単位で分割する設計手法