✅ はじめに
こんにちは!このシリーズでは、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:フォームをコンポーネント単位で分割する設計手法