React Hook Form 基礎知識

## はじめに
個人開発のReactアプリ内でフォームを作成する必要があり
そこでReact Hook Formを初めて使用したのでそこで調べた内容をまとめます。
material uiとの連携なども記述するつもりでしたが
記事が長くなりすぎる為、別記事に記述しようと思います。

## アジェンダ
- React Hook Formとは
- Controlled components と Uncontrolled components
- 使用方法
- use case

### React Hook Formとは

[React Hook Form公式](https://react-hook-form.com/jp/)

React16.8.0から導入されたhooksの仕組みを利用したformライブラリです。
React Hook Form公式でも、少ないコード量でフォームを実装でき、かつ軽量ということをアピールしているように
以下のメリットがあります。

- 少ないコード量でフォームを実装することが出来る
- 軽量なパッケージ
- 他のライブラリと比較した時に少ないレンダリング数
- 依存性の少なさ

### Controlled components と Uncontrolled components

formを作成する際は、`Controlled components`と`Uncontrolled components`の2種類のアプローチがあるかと思います。

- - - 
#### Controlled components
状態管理をReactのスタイルに沿って行います。
フォームの状態は全て属するコンポーネントのstateで管理されるので、各値を更新する場合はstateを更新することになり
再レンダリングが発生しますが、入力値や状態などを直接制御することができます。

#### Uncontrolled components
フォームの状態や入力値は各DOM自身(各input)で制御します。
そのため入力値などが変更された際に再レンダリングは発生しませんが、入力値や状態などを更新するにはDOM操作を行う必要があります。

- - -
ちなみにReactの公式ではcontrolled componentを推奨しています。
>ほとんどの場合では、フォームの実装には制御されたコンポーネント (controlled component) を使用することをお勧めしています。制御されたコンポーネントでは、フォームのデータは React コンポーネントが扱います。非制御コンポーネント (uncontrolled component) はその代替となるものであり、フォームデータを DOM 自身が扱います。

そんな中、React Hook Formは`Uncontrolled components`を採用しています。
その理由としては前述したように、

- コード量を減らせる
- レンダリング数を減らすことが出来る

などのメリットがあるためです。
Uncontrolled componentsを採用しているReact Hook Formでは`ref`を`useForm`に登録します。
これにより、カスタムフックで各入力フォーム要素を完全にコントロールすることが可能になります。

またその反面、子コンポーネントに入力値を渡す必要がある場合などには適していない為
その場合は`controlled component`を採用すべきかと思います。

### 使用方法
 
使用する際の流れを簡単にまとめると以下のようになります。

- useFormをimport
- useFormを初期化し、必要なオブジェクトを分割代入
- 監視対象にregisterの設定
- 送信の設定

また使用するにあたり、各フィールドには登録プロセスの`key`として
ユニークな`name`属性が必要になります。

### use case
公式のサンプルから引用してきました。

```example.jsx
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, watch, errors } = useForm();
  const onSubmit = data => console.log(data);

  console.log(watch("example")); // watch input value by passing the name of it

  return (
    {/* "handleSubmit" will validate your inputs before invoking "onSubmit" */}
    <form onSubmit={handleSubmit(onSubmit)}>
    {/* register your input into the hook by invoking the "register" function */}
      <input name="example" defaultValue="test" ref={register} />
      
      {/* include validation with required or other standard HTML validation rules */}
      <input name="exampleRequired" ref={register({ required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}
      
      <input type="submit" />
    </form>
  );
}
```

前述した流れに沿って説明すると
##### useFormをimport
```example.jsx
import { useForm } from "react-hook-form";
```

##### useFormを初期化し、必要なオブジェクトを分割代入
```example.jsx
  const { register, handleSubmit, watch, errors } = useForm();
```

##### 監視対象にregisterの設定
```example.jsx
<input name="example" defaultValue="test" ref={register} />
```

尚、別のフォームである`exampleRequired`では`register`に条件を渡し
バリデーションのルールを設定しています。
バリデーションの詳細などは、別記事にまとめたいと思います。

```example.jsx
<input name="exampleRequired" ref={register({ required: true })} />
```

##### 送信の設定
```example.jsx
<form onSubmit={handleSubmit(onSubmit)}>
```
`handleSubmit`にフォームの送信ロジックを記述した関数`onSubmit`を渡すことで
送信ボタンが押された際に設定した`onSubmit`が実行されます。
なお`onSubmit`関数には、refにregisterが設定された要素のvalueが,
その要素のnameがプロパティとなり,dataにオブジェクトとして渡されます。

## おわり
今回はReact Hook Formの概要や簡単なuse caseをサンプルを用いて
まとめてみました。
React Hook Formの魅力であるバリデーションやリッチUIとの連携などは
別記事でまとめたいと思います。

最後まで見ていただき、ありがとうございました。