【React/Next.js】ReactでFormを使うならこれを見ろ！React Hook Formチートシート

こんにちは！ReactやNext.jsでフォームを扱う際、バリデーションや入力状態の管理で困ったことはありませんか？フォーム処理は一見シンプルに見えて、実際に実装すると複雑になりがちです。

そんな悩みを解決してくれるのが **React Hook Form** です。今回は、React Hook Formの基本から応用までを網羅したチートシートをお届けします。これを見れば、フォーム実装がぐっと楽になりますよ！

## 目次

1. React Hook Formとは
2. インストール方法
3. 基本的な使い方
4. フォームメソッド一覧
5. バリデーションの実装方法
6. エラーメッセージの表示
7. フォームのリセットと初期値設定
8. 外部コンポーネントとの連携
9. Zodを使ったスキーマバリデーション（おまけ）
10. まとめ

---

## 1. React Hook Formとは

**React Hook Form** は、React Hooksを活用したフォーム管理ライブラリです。主な特徴は以下の通りです。

- **軽量で高速**：再レンダリングを最小限に抑え、高速に動作します。
- **簡単なAPI**：Hooksを活用し、直感的にフォームを構築できます。
- **柔軟なバリデーション**：独自のバリデーションロジックや外部ライブラリとの統合が可能。
- **TypeScriptサポート**：型安全にフォームを扱うことができます。

---

## 2. インストール方法

React Hook Formをプロジェクトに追加するには、以下のコマンドを実行します。

```bash
npm install react-hook-form
```

または

```bash
yarn add react-hook-form
```

---

## 3. 基本的な使い方

### ステップ1：useFormフックの使用

まず、`useForm` フックをインポートします。

```jsx
import { useForm } from 'react-hook-form';
```

### ステップ2：useFormから必要なメソッドを取得

```jsx
const { register, handleSubmit } = useForm();
```

- `register`：入力フィールドをフォームに登録します。
- `handleSubmit`：フォーム送信時のデータ処理を行います。

### ステップ3：フォームの構築

```jsx
function App() {
  const { register, handleSubmit } = useForm();

  const onSubmit = data => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('firstName')} placeholder="First Name" />
      <input {...register('lastName')} placeholder="Last Name" />
      <input type="submit" />
    </form>
  );
}
```

### ステップ4：送信時のデータ処理

```jsx
const onSubmit = data => {
  console.log(data); // フォームデータをコンソールに表示
};
```

---

## 4. フォームメソッド一覧

React Hook Formで使用する主なメソッドとその用途をまとめました。例のコードでは、これらのメソッドを全て使用します。

- **`useForm`**
  - フォームを制御するためのフック。
  - 引数にフォームの設定やバリデーションを指定。

- **`register`**
  - フォーム要素を登録。
  - 入力フィールドに展開して使用。

- **`handleSubmit`**
  - フォーム送信時の処理をラップ。
  - 引数にデータ処理の関数を渡す。

- **`formState`**
  - フォームの状態を保持。
  - `errors`：バリデーションエラー情報。
  - `isSubmitting`：送信中かどうかのフラグ。

- **`reset`**
  - フォームのリセット。
  - 引数に初期値を指定可能。

- **`watch`**
  - フォームの値を監視。
  - 引数にフィールド名を渡して値を取得。

- **`setValue`**
  - フォームの特定のフィールドの値をプログラム的に設定。

- **`getValues`**
  - 現在のフォームの値を取得。

- **`trigger`**
  - バリデーションをプログラム的に実行。

- **`clearErrors`**
  - エラーメッセージをクリア。

- **`setError`**
  - 手動でエラーを設定。

- **`control`**
  - React Hook Formの内部で使用されるコントローラー。

---

## 5. バリデーションの実装方法

### 基本的なバリデーション

`register` メソッドの第二引数にバリデーションルールをオブジェクトで渡します。

```jsx
<input
  {...register('email', {
    required: 'メールアドレスは必須です',
    pattern: {
      value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
      message: '有効なメールアドレスを入力してください',
    },
  })}
/>
```

### カスタムバリデーション

```jsx
<input
  {...register('username', {
    validate: value => value !== 'admin' || 'このユーザー名は使用できません',
  })}
/>
```

---

## 6. エラーメッセージの表示

`formState` オブジェクトからエラー情報を取得します。

```jsx
const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm();
```

フィールドごとのエラーを表示します。

```jsx
<input {...register('email', { required: 'メールアドレスは必須です' })} />
{errors.email && <p>{errors.email.message}</p>}
```

---

## 7. フォームのリセットと初期値設定

### 初期値の設定

`useForm` の引数に `defaultValues` を渡します。

```jsx
const { register, handleSubmit, reset } = useForm({
  defaultValues: {
    firstName: '太郎',
    lastName: '山田',
  },
});
```

### フォームのリセット

```jsx
<button type="button" onClick={() => reset()}>
  リセット
</button>
```

---

## 8. 外部コンポーネントとの連携

### カスタムコンポーネントと`register`

カスタムコンポーネントに `register` を渡して使用します。

```jsx
const CustomInput = ({ label, register, required }) => (
  <>
    <label>{label}</label>
    <input {...register(label, { required })} />
  </>
);

function App() {
  const { register, handleSubmit } = useForm();
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <CustomInput label="FirstName" register={register} required />
      <input type="submit" />
    </form>
  );
}
```

### `Controller`を使用する場合

`Controller` コンポーネントを使用して、サードパーティ製のコンポーネントを制御できます。

```jsx
import { Controller, useForm } from 'react-hook-form';
import Select from 'react-select';

function App() {
  const { control, handleSubmit } = useForm();

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="fruit"
        control={control}
        defaultValue=""
        render={({ field }) => (
          <Select
            {...field}
            options={[
              { value: 'apple', label: 'Apple' },
              { value: 'banana', label: 'Banana' },
            ]}
          />
        )}
      />
      <input type="submit" />
    </form>
  );
}
```

---

## 9. Zodを使ったスキーマバリデーション（おまけ）

バリデーションライブラリ **Zod** を使用して、スキーマベースのバリデーションを実装できます。

### ステップ1：ZodとResolverのインストール

```bash
npm install zod @hookform/resolvers
```

### ステップ2：Zodスキーマの作成

```jsx
import { z } from 'zod';

const schema = z.object({
  username: z.string().min(3, 'ユーザー名は3文字以上で入力してください'),
  email: z.string().email('有効なメールアドレスを入力してください'),
});
```

### ステップ3：useFormでのバリデーション設定

```jsx
import { zodResolver } from '@hookform/resolvers/zod';

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm({
  resolver: zodResolver(schema),
});
```

---

## 10. まとめ

React Hook Formを使うことで、フォームの実装がシンプルかつ効率的になります。バリデーション、エラーメッセージ表示、外部コンポーネントとの連携など、さまざまな機能を柔軟に利用できます。

- **再レンダリングの最小化**：高パフォーマンスなフォーム処理
- **簡潔なAPI**：Hooksを活用した直感的な実装
- **柔軟なバリデーション**：シンプルなバリデーションから複雑なロジックまで対応
- **豊富なメソッド**：フォーム操作に必要なメソッドを完備
- **スキーマバリデーション（Zod）との統合**：型安全なバリデーション（おまけ）

このチートシートが、あなたの開発効率向上に役立てば幸いです！

---

## 参考リンク

- [React Hook Form 公式サイト](https://react-hook-form.com/)
- [React Hook Form ドキュメント (日本語)](https://react-hook-form.com/jp)
- [Zod 公式サイト](https://zod.dev/)

---

**フィードバックや質問があれば、ぜひコメントでお知らせください！**