React-Hook-Formの使い方（Part1：RHFだけでバリデーション）🌟

## はじめに
初見時に公式を読んで「どういうこと？」となったためまとめます。公式読んでスッキリしていない方はこちらを読んでからならスムーズに読めるかもしれません。
また、この記事はpartに分けています。part1ではRHFだけのバリデーション。part2ではyupとの併用。part3ではMUIのバリデーションを行います。

## パッケージインストール

```ts
npm install react-hook-form
yarn add react-hook-form
```
## RHF基本的な使い方
詳細な使い方を説明する前にinput要素の値の取得からバリデーションという一連の流れを説明します。

まずはじめにinput要素にRHFのregisterという関数を適用することで、input要素をRHFから参照できるようにします。次に適用するバリデーションをregister関数に登録します。最後にsubmitボタンを作成しonSubmitで発火する関数をRHFから取得します。

では次の項目から上記で説明した内容とエラーメッセージの出し方の詳細な方法を説明します。
### 目次
* フィールドの登録
* バリデーション適用
* Submitする
* エラーメッセージの出し方

### フィールドの登録
以下React-Hook-Form(RHF)公式のクイックスタートより引用
>React Hook Form の重要なコンセプトの一つは、非制御コンポーネント ([Uncontrolled Components]を
>フックに登録（`register`) し、フォームフィールドの値を検証と収集できるようにすることです。
URL： https://react-hook-form.com/jp/get-started#Quickstart

これだけではよくわからないので補足します。
RHFは使えばinput要素の値(value属性)をuseStateで監視する必要はありません。RHFは非制御コンポーネントの入力を監視してバリデーションすることができます。
バリデーションするにはRHFが提供するカスタムフックである、registerを使って非制御コンポーネントを登録する必要があります。registerはカスタムフックなので以下の方法で取得できます。

```ts
const { register } = useForm();
```
そして実際の非制御コンポーネントの登録は以下のように行います。

```ts
<input {...register("email")} />
```
これで上記のinput要素は"email"というname属性で登録されました。 
これで、フォームフィールドのバリデーションと収集ができるようになりました。
※name属性は必ず一意になるようにする必要があります。


### バリデーション
registerによる登録はできたので、次はバリデーションを適用します。
yupなどのバリデーションライブラリを利用する方法がありますが、今回はRHFで用意されているものを使ってバリデーションしていきます。  
やり方は簡単でregisterの第2引数にバリデーションを定義したオブジェクトを渡すだけです。

```ts
<input {...register("email",  { required: true, maxLength: 20 } )} />   
```
上記は「必須入力」・「最大文字数20文字」というバリデーションを行っています。
他にもあるので公式を見て自分が実装したバリデーションを探してみてください。
https://react-hook-form.com/api/useform/register

### Submitする
次にSubmitしたいと思います。コードは以下の様になっているとします。

```ts
import { useForm } from "react-hook-form";

// コンポーネント
export const App = () => {
  // カスタムフック
  const { register } = useForm();

  // jsx
  return (
    <input {...register("email",  { required: true, maxLength: 20 } )} />         
  );
};
```
まずは、formのHTML要素とsubmitするためのボタンを追加します。

```ts
    <form>
      <input {...register("email",  { required: true, maxLength: 20 } )} />   
      <input type="submit" />
    </form>
```
これで、submitする準備はできました。あとはonSubmitをform要素に持たせればよいです。
ここでuseFormからhandleSubmit関数を取得してonSubmitのイベントリスナーに登録します。

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

<form onSubmit={handleSubmit()}>
    <input {...register("email",  { required: true, maxLength: 20 } )} /> 
    <input type="submit" />
</form>
```
handleSubmitの引数には関数(formSubmitHandler)を渡します。`formSubmitHandler`はinputの値をオブジェクトで受け取ることが出来ます。
またformSubmitHandlerの定義と同時に「formSubmitHandler」と「inputの値」の型定義をしてあげましょう。
1. formSubmitHandlerの型定義はrect-hook-formからimportできます。
2. inputの値はオブジェクトで渡ってくるのでオブジェクトで定義します。
3. useFormにもinputの値の型定義を渡します。

```ts
// 渡す関数の型定義はimportする
import { useForm, SubmitHandler } from "react-hook-form";
// inputの値の型定義
type IFormInputs = {
  email: String;
};
// SubmitHandlerにはinputの値の型定義を渡します。
const formSubmitHandler: SubmitHandler<IFormInputs> = (data) => {
  console.log(data);
};

// コンポーネント
export const App = () => {
  // useFormにも型定義をします
  const { register, handleSubmit } = useForm<IFormInputs>();

  // jsx
  return (
    <form onSubmit={handleSubmit(formSubmitHandler)}>
      <input {...register("email",  { required: true, maxLength: 20 } )} /> 
      <input type="submit" />
    </form>
  );
};
```
コメントなしのコード

```ts
import { useForm, SubmitHandler } from "react-hook-form";

type IFormInputs = {
  email: String;
};

const formSubmitHandler: SubmitHandler<IFormInputs> = (data) => {
  console.log(data);
};

export const App = () => {
  const { register, handleSubmit } = useForm<IFormInputs>();

  return (
    <form onSubmit={handleSubmit(formSubmitHandler)}>
      <input {...register("email",  { required: true, maxLength: 20 } )} /> 
      <input type="submit" />
    </form>
  );
};
```

これで完成です。20文字以下の入力があればsubmitした瞬間にformSubmitHandlerが動いて
console.logに以下の様な内容が出力されるはずです。

```ts
{email: "入力値"}
```

### エラーメッセージの出し方
エラーメッセージを出すのは簡単です。
useFormからerrorオブジェクトを取得し、そのエラーオブジェクトの中身がある場合はエラーメッセージを出すようにします。
エラーオブジェクはregisterで登録したname属性のプロパティを持ちます。submitの時にバリデーションをパスできなければerrorオブジェクトの中身が生成されます。

```ts
import { useForm, SubmitHandler } from "react-hook-form";

type IFormInputs = {
  email: String;
};

const formSubmitHandler: SubmitHandler<IFormInputs> = (data) => {
  console.log(data);
};

export const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors } // errorオブジェクト
  } = useForm<IFormInputs>();

  return (
    <form onSubmit={handleSubmit(formSubmitHandler)}>
      <input {...register("email", { required: true, maxLength: 20 })} />
      <input type="submit" />
      <br />
      // errorオブジェクトのemailが値を持つとき
      {errors.email && <span style={{ color: "red" }}>エラー</span>}
    </form>
  );
};
```

## 最後に
以上でRFHだけを使ったバリデーションの説明は終わりです。より詳細なバリデーション方法を知りたい場合は公式を読むと良いでしょう。また、ここで紹介しなかったwatchなどのuseFormが持つAPIを確認することも重要なことかもしれません。（watchは使い道がわからなかったので、紹介できませんでした。）

part2ではyupを使ったバリデーションを説明します。part3ではMUIをバリデーションしたいと思います。

以上です。記事を読んでくださりありがとうございました。