React Hook Formを使ったフォーム管理

React Hook Formは、Reactアプリケーションにおけるフォーム管理を簡素化するための強力なライブラリです。特に、`useForm`カスタムフックは、フォームの状態管理やバリデーションルールの設定を容易にする中心的な機能です。

## 基本的な使用例

以下は、`useForm`フックを使用した基本的な例です。

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

interface FormValues {
 firstName: string;
 lastName: string;
 email: string;
}

const MyForm: React.FC = () => {
 const { register, handleSubmit, errors } = useForm<FormValues>();

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

 return (
   <form onSubmit={handleSubmit(onSubmit)}>
     <input name="firstName" ref={register({ required: true })} />
     {errors.firstName && <span>This field is required</span>}

     <input name="lastName" ref={register({ required: true })} />
     {errors.lastName && <span>This field is required</span>}

     <input name="email" ref={register({ required: true, pattern: /^\S+@\S+$/i })} />
     {errors.email && <span>This field is required and must be a valid email</span>}

     <button type="submit">Submit</button>
   </form>
 );
};

export default MyForm;
```
上記の例では、useFormフックを使用してフォームの状態を管理し、registerメソッドを使用して各入力要素をフォームに登録しています。handleSubmitメソッドは、フォームの送信時に呼び出され、フォームデータを引数として受け取ります。errorsオブジェクトを使用して、バリデーションエラーを表示しています。

## フォームの設定とカスタマイズ
useFormフックには、いろいろな設定ができるプロパティがあります。これらのプロパティを使うと、フォームの動きをカスタマイズできます。

例えば、modeっていうオプションがあるんですが、これを使うと、ユーザーがフォームを送信する前にいつバリデーション（入力チェック）をするかを選べます。

- onSubmit: フォームを送信したときにバリデーションをする
- onBlur: 入力欄からフォーカスが外れたときにバリデーションをする
- onChange: 入力欄の内容が変更されるたびにバリデーションをする
- onTouched: 入力欄に一度でもフォーカスがあたったあと、フォーカスが外れたときにバリデーションをする

こんな感じで、バリデーションのタイミングを自分で決められるんですよ。他にも、フォームの初期値を設定したり、エラーメッセージの表示方法を変えたりできるプロパティがあります。

```tsx
const { register, handleSubmit, errors } = useForm<FormValues>({
  mode: 'onBlur',
  defaultValues: {
    firstName: 'John',
    lastName: 'Doe',
    email: 'johndoe@example.com',
  },
});
```
スキーマバリデーションのプロパティには、resolverとcontextがあります。resolverを使用すると、好みのスキーマバリデーションライブラリ（例えば、Yup、Joi、Superstruct）と統合できます。これにより、複雑なバリデーションルールを定義し、フォームの入力値を効果的に検証できます。contextプロパティは、スキーマバリデーションに追加のコンテキストを提供するために使用されます。

```tsx
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';

const schema = yup.object().shape({
  firstName: yup.string().required(),
  lastName: yup.string().required(),
  email: yup.string().email().required(),
});

const { register, handleSubmit, errors } = useForm<FormValues>({
  resolver: yupResolver(schema),
});
```
## バリデーションルールの適用
registerメソッドは、入力要素やselect要素をReact Hook Formに登録し、バリデーションルールを適用するために使用されます。HTML標準に基づくバリデーションルール（required、min、max、minLength、maxLength、patternなど）に加えて、カスタムバリデーションメソッドを定義することもできます。これにより、アプリケーションの要件に合わせた柔軟なバリデーションが可能になります。

```tsx
const { register, handleSubmit, errors } = useForm<FormValues>();

<input
  name="age"
  ref={register({
    required: true,
    min: 18,
    max: 99,
    validate: (value) => value % 2 === 0,
  })}
/>;
```
## 初期値の設定
defaultValueは、フォームの初期値を設定するために使用されます。defaultValuesに、初期値を持ったオブジェクトを渡すだけで、フォームの各入力欄に初期値が表示されるようになります。

初期値を設定しておくと、ユーザーが情報を編集するときに、現在の値を参考にしながら編集できるので、とても便利ですよね。

また、フォームをリセットするときにも、defaultValuesで設定した初期値に戻すことができます。

## フォームの状態管理
useFormフックから返されるオブジェクトには、フォーム全体の状態に関する情報が含まれています。例えば、isDirtyプロパティは、ユーザーが入力要素を変更するとtrueに設定されます。isValidプロパティは、フォームが有効な状態であるかどうかを示します。isSubmittingプロパティは、フォームが送信中であるかどうかを示します。これらのプロパティを使用して、フォームの状態に基づいて条件付きのUI表示やアクションを実行できます。

```tsx
const { formState: { isDirty, isValid, isSubmitting } } = useForm<FormValues>();

return (
  <form onSubmit={handleSubmit(onSubmit)}>
    {/* ... */}
    <button type="submit" disabled={!isValid || isSubmitting}>
      {isSubmitting ? 'Submitting...' : 'Submit'}
    </button>
    {isDirty && <p>Form has unsaved changes.</p>}
  </form>
);
```
### 値の監視
watchメソッドは、指定した入力要素の値の変更を監視し、その値を返します。これは、他の入力要素の値に基づいて動的に値を更新する場合に便利です。例えば、パスワードの確認フィールドを実装する際に、watchメソッドを使用してパスワードの入力値を監視し、確認フィールドの値と比較することができます。

```tsx
const password = watch('password');

return (
  <form onSubmit={handleSubmit(onSubmit)}>
    <input name="password" ref={register({ required: true })} />
    <input
      name="confirmPassword"
      ref={register({
        required: true,
        validate: (value) => value === password,
      })}
    />
    {errors.confirmPassword && <span>Passwords do not match</span>}
    {/* ... */}
  </form>
);
```

## エラーハンドリングとリセット
React Hook Formは、エラーハンドリングやフォームのリセットなどの一般的なフォーム機能も提供しています。errorsオブジェクトを使用して、バリデーションエラーを簡単に表示できます。resetメソッドを使用して、フォームの状態をリセットできます。

```tsx

const { register, handleSubmit, errors, reset } = useForm<FormValues>();

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

return (
  <form onSubmit={handleSubmit(onSubmit)}>
    {/* ... */}
    <button type="button" onClick={() => reset()}>
      Reset
    </button>
  </form>
);
```

### 他のライブラリやツールとの連携
また、React Hook Formは、他のライブラリやツールと連携することができます。例えば、Material-UIやBootstrapなどのUIライブラリと組み合わせて、美しくて使いやすいフォームを作成できます。また、Redux、MobX、Recoilなどの状態管理ライブラリと組み合わせて、アプリケーション全体の状態を管理することもできます。


# まとめ
React Hook Formは、開発者にとって効率的でユーザーフレンドリーなフォームを作成するための強力なツールです。シンプルなAPIと柔軟なカスタマイズ機能により、さまざまなアプリケーションの要件に対応できます。フォームの状態管理やバリデーションを手動で実装する必要がなくなるため、開発者はビジネスロジックに集中することができます。