フォーム画面を作成する方法【React Hook Form + MUI】

# はじめに
React Hook Form (react-hook-form) と Material-UI (MUI) を組み合わせて、効率的で美しいサインアップフォームを作成する方法について解説します。具体的なコードを使いながら、フォームのセットアップから各入力フィールドの管理までを整理します。

# 参考
https://zenn.dev/castingone_dev/articles/bec833cba5e7c9

# 作成の例

### 画面のイメージ
<img src="https://i.gyazo.com/26f5657de50e56b0d825da67aed99851.png" alt="Image from Gyazo" width="300" />


以下のコードは Next.js で react-hook-form と MUI を使ったサインアップフォームの例です。
```
import { NextPage } from 'next';
import { useForm, Controller } from 'react-hook-form';
import { TextField, Button, Typography, Box } from '@mui/material';

interface SignUpFormData {
  username: string;
  email: string;
  password: string;
  confirmPassword: string;
}

const SignUpForm: NextPage = () => {
  // フォームのセットアップ
  const { control, handleSubmit, watch } = useForm<SignUpFormData>({
    defaultValues: {
      username: '',
      email: '',
      password: '',
      confirmPassword: '',
    },
  });

  // フォーム送信時の処理
  const onSubmit = (data: SignUpFormData) => {
    console.log('サインアップデータ:', data);
  };

  // パスワードと確認パスワードが一致しているかチェック
  const password = watch('password');
  const confirmPassword = watch('confirmPassword');

  return (
    <Box
      sx={{
        maxWidth: 400,
        margin: 'auto',
        padding: 4,
        backgroundColor: '#f9f9f9',
        borderRadius: '10px',
        boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
      }}
    >
      <Typography variant="h4" sx={{ color:'black',textAlign: 'center', mb: 4 }}>
        サインアップ
      </Typography>
      <form onSubmit={handleSubmit(onSubmit)}>
        {/* ユーザー名 */}
        <Controller
          name="username"
          control={control}
          render={({ field }) => (
            <TextField
              {...field}
              label="ユーザー名"
              variant="outlined"
              fullWidth
              margin="normal"
              sx={{ backgroundColor: 'white' }}
            />
          )}
        />
        <Controller
          name='email'
          control={control}
          render = {({field}) =>
            <TextField
              {...field}
              label = 'Eメール'
              variant = 'outlined'
              fullWidth
              margin='normal'
              sx={{bgcolor:'white'}}
              /> 
          }
        />

        {/* パスワード */}
        <Controller
          name="password"
          control={control}
          render={({ field }) => (
            <TextField
              {...field}
              type="password"
              label="パスワード"
              variant="outlined"
              fullWidth
              margin="normal"
              sx={{ backgroundColor: 'white' }}
            />
          )}
        />

        {/* パスワード確認 */}
        <Controller
          name="confirmPassword"
          control={control}
          render={({ field }) => (
            <TextField
              {...field}
              type="password"
              label="パスワード確認"
              variant="outlined"
              fullWidth
              margin="normal"
              sx={{ backgroundColor: 'white' }}
              error = {password !== confirmPassword}
              helperText={
                password !== confirmPassword
                ? 'パスワードが一致しません'
                : ''
              }
              
            />
          )}
        />

        {/* 送信ボタン */}
        <Button
          type="submit"
          variant="contained"
          color="primary"
          fullWidth
          sx={{ mt: 2 }}
          disabled={password !== confirmPassword}
        >
          サインアップ
        </Button>
      </form>
    </Box>
  );
};

export default SignUpForm;

```

## 各部分の解説
### useForm フック
useForm は react-hook-form から提供され、フォーム全体の状態管理を簡単にします。control はフォームフィールドを管理するオブジェクトで、handleSubmit はフォーム送信時に使用する関数です。

### Controller コンポーネント
- Controller は react-hook-form が提供するコンポーネントで、外部の UI ライブラリ（今回は MUI）とフォームの状態管理を連携させる役割を果たします
- name プロパティ: 入力フィールドの名前を指定します
- control プロパティ: useForm フックから取得した control オブジェクトを渡します
- render プロパティ: 実際の入力フィールドを描画するための関数を指定します。field には入力フィールドの状態やイベントハンドラーが含まれています

### TextFieldコンポーネント
MUI の TextField コンポーネントは、フォームの入力フィールドを作成するために使用されます。{...field} によって、react-hook-form の状態管理機能を展開します。

## Controller と field の理解

- Controller コンポーネントを使うことで、MUI の TextField と react-hook-form の状態管理がスムーズに連携します
- {...field}: field には value, onChange, onBlur などのプロパティが含まれており、これを展開して TextField に渡すことで、入力の状態が自動で管理されます

## バリデーションと送信

- フォーム送信時は、handleSubmit を使ってデータを受け取り、onSubmit 関数で処理します
- watch 関数を使って、入力値をリアルタイムで監視し、パスワードの一致をチェックしています

# 終わりに
- react-hook-form と MUI を組み合わせることで、簡単に美しいフォームを作成できます
- Controller コンポーネントの使い方を理解することで、外部 UI ライブラリとの連携がスムーズになります