はじめに
React Hook Formというフォームを作ることに特化したライブラリの基礎を紹介します。
今の業務で使っているのですが、見様見真似でやっている状態なので備忘も兼ねてまとめていきます。
なお、本記事においては
React 18.2.0
TypeScript 5.2.2
Vite 5.2.0
を使用しています。
React Hook Formとは
概要
その名の通り、フォームを作ることに特化したライブラリです。
Performant, flexible and extensible forms with easy-to-use validation.
とあるように、パフォーマンス、柔軟性、拡張性に優れており、また簡単にバリデーションを実行できるのが特徴です。
どのようなものが作れるか
import { useForm, SubmitHandler } from "react-hook-form";
type Inputs = {
example: string;
exampleRequired: string;
};
const App = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Inputs>();
const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input defaultValue="test" {...register("example")} />
<input {...register("exampleRequired", { required: true })} />
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
</form>
);
};
export default App;
公式サイトから抜粋してきたコードです。
(コメントなど一部不要な記載を削除)
2つめの入力欄が必須である旨のメッセージが出ます。
値を入力するとメッセージは消えます。
この状態で送信ボタンを押すと
それだけか、と思うかもしれませんが、実は結構すごいのです。
まずバリデーションの処理を書いていません。
{ required: true }
みたいなそれらしきものは設定していますが、自身でフォームを作成する際にはしっかり書く必要があります。
また、フォームの入力値を管理するstateがありません。
送信後の値を取得する処理も書いていません。
この辺をまるっとやってくれているのがReactHookFormです。
では早速どのように書くのかを見ていきます。
ReactHookFormを試す
導入
まずはインストールする必要があるので(プロジェクトは作成済の想定)、以下のコマンドを入力します。
npm install react-hook-form
入力フィールドの登録
この部分が一番大事な肝になります。
バリデーションとデータの送信に紐づけるための処理になります。
import { useForm, SubmitHandler } from "react-hook-form";
interface IFormInput {
firstName: string;
check: string;
}
const App = () => {
const {
register,
handleSubmit,
} = useForm<IFormInput>();
const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>First Name</label>
<input {...register("firstName")}/>
</div>
<div>
<label>Check</label>
<input type="checkbox" {...register("check")}/>
</div>
<input type="submit" />
</form>
);
};
export default App;
useFormの使用
ReactHookFormの基本はuseFormというカスタムフックを使うことです。
このフックを使うことにより、様々な機能を使うことができます。
このuseFormにはオブジェクトの形で引数を渡すことでいろいろ設定ができるのですが、今回は割愛して、戻り値であるregister
という関数に着目します。
register関数
inputタグ、またはselectタグに対して使用します。
引数としてname`属性に設定したい値を設定することで、バリデーションや値の送信時に紐づけることができます。
バリデーションの適用
先ほど使用したregister関数に、どんなときにエラーとしたいのかという情報を追加できます。
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>First Name</label>
<input
{...register("firstName", {
required: true,
minLength: { value: 3, message: "3文字以上で入力して下さい" },
})}
/>
</div>
<div>
<label>Check</label>
<input
type="checkbox"
{...register("check", {
required: { value: true, message: "check is required" },
})}
/>
</div>
<input type="submit" />
</form>
);
バリデーションの設定
register関数に、オブジェクト形式で引数を渡します。
requierdの他、min, max, minLength, maxLengthなどhtmlタグに設定することができる属性は一通り設定が可能です。
また、単純にバリデーションに使用したい設定値を渡す代わりに
{value:設定値, message:'エラーメッセージ'}
の形式でオブジェクトを渡すことで、エラーメッセージのカスタマイズも可能になっています。
エラーハンドリング
上記でバリデーションの設定を行いましたが、今の状態でバリデーションエラーを起こしても何も起きません。
次にエラーハンドリングをする必要があります。
import { useForm, SubmitHandler } from "react-hook-form";
interface IFormInput {
firstName: string;
check: string;
}
const App = () => {
const {
register,
formState: { errors },
handleSubmit,
} = useForm<IFormInput>();
const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>First Name</label>
<input
{...register("firstName", {
required: true,
minLength: { value: 3, message: "3文字以上で入力して下さい" },
})}
/>
{errors.firstName?.type === "required" && "必須です"}
{errors.firstName?.type === "minLength" && errors.firstName.message}
</div>
<div>
<label>Check</label>
<input
type="checkbox"
{...register("check", {
required: { value: true, message: "check is required" },
})}
/>
{errors.check && errors.check.message}
</div>
<input type="submit" />
</form>
);
};
export default App;
errosの使用
エラーの情報を扱うにはuseFormフックが返すformState
のerrors
を使用します。
errors
にはregister
関数で登録したname
に紐づく形でエラーの情報が格納されます。
エラーがない場合には何も入ってきません。
errors
のname
に紐づくtype
にはどのタイプのバリデーションエラーなのかが格納されます。
firstName
には必須チェック(required)と、最低文字数チェック(minLength)を設定しているので、それぞれのエラーについて出力するメッセージを指定しています。
必須チェックの場合はregister
関数においてmessage
を指定しなかったので、任意のメッセージを指定。
最低文字数チェックの場合には設定したmessage
を取得しています。
このように、error
からバリデーションの結果を取得することによって、エラー時の挙動を決めることができます。
挙動確認
ではここまでで一通り設定ができたので動きを確認します。
そのまま送信ボタンを押すと、それぞれ必須チェックに引っかかります。
値を設定すると、Checkのエラーは消えますが、FirstNameは文字数のエラーに変わります。
まとめ
ReactHookFormを使ってお手軽にフォームの作成、バリデーションを実施する方法を確認してきました。
自分であれこれ考えなくても、お作法に則ってパラメータを設定するだけであとはやってくれるので非常に楽です。
まだ上記で紹介した者は本当にさわりの部分だけなので、また機会を見つけていろいろな機能を紹介していきます。