Reactでフォームを作成するときに便利で優秀なライブラリ、React Hook Form!
素のHTMLで使用するなら導入は簡単ですが、MUI等のUIライブラリと組み合わせると、記述が少し複雑になりますよね。その違いを比較して整理しましたのでご紹介します。
環境
- react @18.2.0
- vreact-hook-form @7.41.5
- typescript @4.9.4
- mui/material @5.11.4
※全て2023年1月13日時点の最新versionです。
プロジェクト作成・ライブラリインストール
違いを比較するために、プロジェクトの作成とライブラリのインストールをします。
Create React App
% yarn create react-app react-hook-form_radio-button-ts --template typescript
yarnを使い、typescriptで作成します。
React Hook Form
% yarn add react-hook-form
MUI
% yarn add @mui/material @emotion/react @emotion/styled
フォームを作成
React Hook Formのドキュメントに、MUIを使ったサンプルとして以下が挙げられていますので、これを使ってフォームを作成してみましょう!
MUIのチェックボックス
import { useForm, Controller, SubmitHandler } from "react-hook-form";
import Checkbox from "@mui/material/Checkbox";
interface IFormInputs {
MyCheckbox: boolean;
}
function App() {
const { handleSubmit, control } = useForm<IFormInputs>({
defaultValues: {
MyCheckbox: false,
},
});
const onSubmit: SubmitHandler<IFormInputs> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="MyCheckbox"
control={control}
rules={{ required: true }}
render={({ field }) => <Checkbox {...field} />}
/>
<input type="submit" />
</form>
);
}
export default App;
サンプルはMaterial UIのバージョンがv4になっていたので、それだけv5に置き換えています。
上記を実行すると以下の画面となります。
チェックを入れ送信をすると、consoleには以下のログが出力されます。
{MyCheckbox: true}
詳細は後述しますので、ここではサラッと目を通すくらいで大丈夫です。
素のHTMLで作ったチェックボックス
上記同様に、チェックボックスをMUIを使わない素のHTMLで記述する方法を見てみましょう。
import { useForm, SubmitHandler } from "react-hook-form";
interface IFormInputs {
MyCheckbox: boolean;
}
function App() {
const { handleSubmit, register } = useForm<IFormInputs>({
defaultValues: {
MyCheckbox: false,
},
});
const onSubmit: SubmitHandler<IFormInputs> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input type="checkbox" {...register("MyCheckbox")} />
<input type="submit" />
</form>
);
}
export default App;
素のHTMLのinputタグで、type=”checkbox”を使った方法だと、一行で書くことができ、MUIと比べシンプルです。
これを実行すると以下の画面となります。
この処理の流れを確認してみましょう!
- register関数により、hookにinput要素の内容が登録される
- submitボタンが押される
- input要素をvalidationする
- onSubmitが呼び出される
registerメソッドだけがさすがにわかりにくいので詳しく説明します。
registerとは
公式のドキュメントはこちらになります。
registerメソッドの特徴は以下の2点です。
- input と select要素で使うことができます。
- 4つの働きをする。
具体的例をあげます。
<input {...register('firstName')} />
この一行で以下の4つの機能を含んでいます。
<input
onChange={onChange} // assign onChange event
onBlur={onBlur} // assign onBlur event
name={name} // assign name prop
ref={ref} // assign ref prop
/>
これだけの機能を含んでいるのでregisterと記述するだけで、change eventが機能するようになるというわけです。
registerを使った素のHTMLでのシンプルな使い方がわかったところで、MUIを使った方法を改めて見ましょう。
Controller
React Hook FormでMUIを使用するにはControllerを使用する必要があります。
公式ドキュメントがこちらです。
Controllerが必要な理由
import { useForm, Controller, SubmitHandler } from "react-hook-form";
import Checkbox from "@mui/material/Checkbox";
interface IFormInputs {
MyCheckbox: boolean;
}
function App() {
const { handleSubmit, control } = useForm<IFormInputs>({
defaultValues: {
MyCheckbox: false,
},
});
const onSubmit: SubmitHandler<IFormInputs> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="MyCheckbox"
control={control}
rules={{ required: true }}
render={({ field }) => <Checkbox {...field} />}
/>
<input type="submit" />
</form>
);
}
export default App;
React Hook Formは、uncontrolled componentsを扱います。しかし、MUIはcontrolled componentです。
そのため、React Hook Formでcontrolled componentを扱う場合はControllerを使う必要があるということです。
ここでいうuncontrolled、controlledとは何でしょう?
日本語にすると、非制御コンポーネント、制御されたコンポーネントとなり、Reactのドキュメントに記載されています。以下に説明します。
非制御コンポーネントとは(React Hook Form)
- フォームの実装方法としてReactが推奨している方法
- フォームのデータの扱いをDOM自身が担う
- stateの更新を行う場合は、refを使用してDOMからフォームの値を取得する
制御されたコンポーネントとは(MUI)
- React コンポーネントが、後続するユーザ入力でフォームで起きることも制御できる状態のことをいう
- 以下の2つを結合している
1.<input>
、<textarea>
、<select>
のような自身で状態を保持するフォーム要素
2. setStateで更新されるstate - フォームのデータの扱いをReactコンポーネントが担う
React Hook Formは非制御コンポーネントを採用した作りとなっているのですが、MUIは制御されたコンポーネントであるためControllerを使う必要があるというわけです。
Controllerの使い方
上記コードの内、Controllerの中身の以下について詳しく説明します。
<Controller
name="MyCheckbox"
control={control}
rules={{ required: true }}
render={({ field }) => <Checkbox {...field} />}
/>
- name: input要素のユニーク名
- control: componentを登録するためのメソッドです。Checkboxのコンポーネントを使用しているため、これが必要になります。
- rules: validationのルールを記載します。
- render: Reactのメソッドで、Reactの要素を返す関数を受け取り、それを呼び出すことができます。これを使うことで、外部コンポーネントであるMUIとの統合ができています。
ここで使われているfieldには、「onChange, onBlur, value, name, ref」の5つがあり、子コンポーネントに提供することができます。
番外:React Hook Formをなぜ使うのか
順番が前後してしまっていますが、そもそもReact Hook Formを使う必要があるのか、使うメリットは何なのかを理解しておきたいと思います。
フォームにReact Hook Formを使うメリット
- バンドル(JavaScriptファイル)サイズが小さくでき、アプリのパフォーマンスを改善できる
- Reactのイベントシステムを使用していないため、フォーム入力のたびにDOM更新がされることはなく、処理の負荷が少なくなる。
Reactのイベントシステムを使うと、コンポーネントのライフサイクルに沿って、イベントハンドラーを呼び出し、DOMの更新の管理がされることになる。 - バリデーションの設定を簡単に行うことができる
まとめ
React Hook FormでのMUIを使う場合は、Controllerメソッドを使用し外部コンポーネントを使用できるようにcontrollerオブジェクトやrender propを用います。
以上、お読みいただきありがとうございました。
コメント