2025年5月25日日曜日

【第3回】フォームの作成とバリデーション(MUI + React Hook Form)

✅ はじめに

こんにちは!このシリーズでは、React + Vite + TypeScript + MUIという現代的な技術スタックを使って、Webアプリを開発する方法をステップバイステップで解説しています。

第3回となる今回は、フォームの作成とバリデーションを扱います。UIには MUI を、バリデーションには React Hook Form を使って、シンプルかつ堅牢なフォームを作成していきましょう。

📦 使用する技術スタック

ツール バージョン 説明
React Hook Form v7.x フォーム管理とバリデーション
MUI v5.x マテリアルデザインベースのUIコンポーネント
TypeScript 5.x 型安全なJavaScript
Vite 5.x 高速な開発環境とビルドツール

🚀 実装手順

1. プロジェクトの作成

まずは、Viteを使って新しいプロジェクトを作成します:

npm create vite@latest my-react-form-app -- --template react-ts
cd my-react-form-app
npm install

2. 必要なパッケージのインストール

MUIとReact Hook Formをインストールします:

npm install @mui/material @emotion/react @emotion/styled @fontsource/roboto react-hook-form

3. フォームコンポーネントの作成

src/pages/UserForm.tsxを作成します:

import type { FC } from 'react';
import { useForm } from 'react-hook-form';
import { TextField, Button, Container, Typography, Paper } from '@mui/material';

type FormData = {
  name: string;
  email: string;
};

const UserForm: FC = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>();

  const onSubmit = (data: FormData): void => {
    alert(`名前: ${data.name}\nメール: ${data.email}`);
  };

  return (
    <Container maxWidth="sm">
      <Paper elevation={3} sx={{ p: 4, mt: 4 }}>
        <Typography variant="h4" component="h1" gutterBottom>
          ユーザーフォーム
        </Typography>
        <form onSubmit={handleSubmit(onSubmit)} noValidate>
          <TextField
            fullWidth
            label="名前"
            margin="normal"
            {...register('name', { required: '名前は必須です' })}
            error={!!errors.name}
            helperText={errors.name?.message}
          />
          <TextField
            fullWidth
            label="メール"
            margin="normal"
            {...register('email', {
              required: 'メールは必須です',
              pattern: {
                value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
                message: '有効なメールアドレスを入力してください',
              },
            })}
            error={!!errors.email}
            helperText={errors.email?.message}
          />
          <Button 
            variant="contained" 
            type="submit" 
            sx={{ mt: 2 }}
            fullWidth
          >
            送信
          </Button>
        </form>
      </Paper>
    </Container>
  );
};

export default UserForm;

4. App.tsxの更新

最後に、src/App.tsxを更新してフォームを表示します:

import { ThemeProvider, createTheme } from '@mui/material';
import UserForm from './pages/UserForm';

const theme = createTheme({
  typography: {
    fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
  },
});

function App() {
  return (
    <ThemeProvider theme={theme}>
      <UserForm />
    </ThemeProvider>
  );
}

export default App;

🎯 主要なポイント

1. React Hook Formの基本概念

  • useForm: フォームの状態管理とバリデーションを提供
  • register: フォームフィールドの登録とバリデーションルールの設定
  • handleSubmit: フォーム送信時の処理を管理
  • formState: エラー状態などのフォーム状態を管理

2. MUIフォームコンポーネント

  • TextField: 入力フィールドのスタイリングとエラー表示
  • Container: レスポンシブなレイアウト
  • Paper: カード風のコンテナスタイリング

3. TypeScriptの型安全性

  • FC型: Reactの関数コンポーネントの型定義
  • FormData型: フォームデータの型定義
  • 明示的な戻り値の型: 関数の戻り値型を指定

🔚 まとめ

今回は、React Hook FormとMUIを組み合わせて、型安全なバリデーション機能付きフォームを実装しました。この組み合わせは実用的で、多くの商用アプリでも採用されています。

📚 次回予告

【第4回】状態管理とAPI通信(React + Axios)