【React】React Hook Form の基本的な使い方。

## 概要
Reactを用いたWeb開発にて、フォームを作成する際、useState等を用いて作成することもできますが、onChangeイベントで入力文字をリアルタイムに管理するなど、色々と実装が面倒くさいです。

そこで、React Hook FormのuseFormメソッドを使って、より簡単にFormを実装する方法を紹介します。

<br>
↓実装イメージ

①タイトル、期日、メモを入力し、追加ボタンを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817219/1f732e6e-bb54-ca94-fcec-5e6c5d95acc8.png)

②コンソールに、送信した内容がオブジェクトとして表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817219/ad4a3f74-350c-63e2-3ec0-67a8a2118808.png)


## 前提知識
* Reactの基礎知識
* JavaScriptの基本的な知識
* TypeScriptの基本的な知識
* HTMLの基礎知識

## 学んだ技術の説明
### 技術の概要
useFormフックを使うことで、フォームの登録、バリデーション、エラーメッセージの表示、フォームのリセットなどを簡単に実装できます。


### インストールと設定
React Hook Formのインストール

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

### 基本的な使い方
以下は、上記「実装イメージ」のサンプルコードです。

```tsx
"use client";
import React from "react";

// useFormをインポート
import { useForm } from "react-hook-form";

// フォームで送られてくるタスクの型を定義
interface TaskItem {
  title: string;
  deadLine: string;
  memo: string;
}

export default function Home() {
  // useFormを利用したフォームの処理
  const {
    register,
    handleSubmit,
    formState: { errors },
    reset,
  } = useForm<TaskItem>({ mode: "onSubmit" });

  // 追加ボタン押下時に発火する関数
  const onSubmit = async (taskItem: TaskItem) => {
    console.log(taskItem);
    // 通常はここでAPI通信によるデータベースの更新・保存などを行う。

    // フォームの内容をリセット
    reset();
  };

  return (
    <div>
      <h3 className="font-bold">タスク作成</h3>
      {/* フォームの作成　*/}
      <form
        onSubmit={handleSubmit(onSubmit)}
        className="w-96 mt-4 mb-10 p-4 border rounded-lg shadow"
      >
        <div className="mb-4">
          <label className="block text-white text-sm font-bold mb-2">
            タイトル：
            <input
              type="text"
              {...register("title", { required: "タイトルは必須です。" })}
              className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
            />
            {/* バリデーションに引っかかった時に表示される */}
            <p className="text-red-500 text-xs italic">
              {errors.title?.message as React.ReactNode}
            </p>
          </label>
        </div>
        <div className="mb-4">
          <label className="block text-white text-sm font-bold mb-2">
            期日：
            <input
              type="date"
              {...register("deadLine")}
              className="shadow border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
            />
          </label>
        </div>
        <div className="mb-4">
          <label className="block text-white text-sm font-bold mb-2">
            メモ：
            <textarea
              {...register("memo")}
              className="shadow border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
            ></textarea>
          </label>
        </div>
        <div className="flex items-center justify-between">
          <button
            type="submit"
            className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
          >
            追加
          </button>
        </div>
      </form>
    </div>
  );
}

```
### 詳細説明

上記のコードを処理ごとに説明します。

#### useFormを利用したフォームの処理

```jsx
  const {
    register,
    handleSubmit,
    formState: { errors },
    reset,
  } = useForm<TaskItem>({ mode: "onSubmit" });
```

◯ register

* フォームの入力要素のState管理、バリデーション設定、デフォルト値設定などが可能。
* jsx内のinput要素のタグ（input, textareaなど）の属性に以下を入力する。

{...register（"キー",  { バリデーションの制約: "エラーメッセージ" })}

例）
```jsx
<label className="block text-white text-sm font-bold mb-2">
        タイトル：
        <input
            type="text"
            {...register("title", { required: "タイトルは必須です。" })}
            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
        />
        {/* バリデーションに引っかかった時に表示される */}
        <p className="text-red-500 text-xs italic">
            {errors.title?.message as React.ReactNode}
        </p>
</label>
```

・キー
フォームから送信された内容はオブジェクトとして受け取られるため、その際のキーとなる。入力内容がvalueとなる。

・バリデーションの制約
バリデーションのルールの設定。
required:必須項目、maxLength：最大文字数など、さまざまな設定ができる。

・エラーメッセージ
バリデーションに引っかかった際のメッセージ。
「errors.キー.message」に格納される。


上記コードの場合、
inputエリアに入力された項目は、キー「title」のvalueとなる。
また、必須入力のバリデーションが設定されており、空白のままフォームを送信すると、inputBoxの下に、「タイトルは必須です。」と表示される。

<br>

◯handleSubmit

* フォームが送信されたときにバリデーションチェックを行い、成功した場合に指定したコールバック関数を実行する。
→FormタグのonSubmit属性に設定。引数にコールバック関数を渡す。

* コールバック関数に、フォームに入力された内容をオブジェクトの形で渡してくれる。
→以下の場合、taskItemというオブジェクトでフォームの入力内容が渡される。

```jsx
  <form
    onSubmit={handleSubmit(onSubmit)}
    className="w-96 mt-4 mb-10 p-4 border rounded-lg shadow"
  >
```

```jsx
 const onSubmit = async (taskItem: TaskItem) => {
    console.log(taskItem);
    // 通常はここでAPI通信によるデータベースの保存などを行う。

    // フォームの内容をリセット
    reset();
  };
```
<br>


◯FormState

* フォーム内の入力の有無や送信の状態などを取得できる。
* 今回定義しているerrosには、バリデーションのエラーのオブジェクトが入る。
* その他、送信中を示すisSubmittingや、フォームの送信の成功を示すisSubmitSuccessfulなど、さまざまな値がある。

<br>

◯reset

* フォームの入力フィールドを初期状態にリセットするために使用される
* フォームの送信後にフィールドをクリアしたり、特定の条件下でフォームのデータをリセットしたりするのに便利。

```jsx
reset();
```


## まとめ
React Hook Formを使用すると、Reactでのフォーム管理が非常に簡単になります。
useFormを使うことで、少ないコード量で効率的にフォームのバリデーションやエラーメッセージの表示を実装できます。
これにより、開発者はより重要なロジックに集中することができます。

今回紹介した機能以外にも、さまざまな機能（設定）がありますので、興味のある方は調べてみてください！

初心者でも割と簡単に実装できると思うので、ぜひ使ってみてください！

## 参考資料
https://react-hook-form.com/