React-Hook-Formのおさらい
はじめに
Reactの基礎知識を学び直しています。
この記事ではReact-Hook-Formについて、簡単なフォームを作りながらまとめています。
言語はTypeScript、実行環境はCodeSandboxを使用しています。
React Hook Formとは
Reactでのフォーム送信をより便利にするライブラリです。
パフォーマンス、柔軟性、拡張性に優れた使いやすいフォームバリデーションライブラリ
https://react-hook-form.com/
1.フォームバリデーションの実装
フォームには、ユーザー名(必須、10文字以上)、メールアドレス(必須、メール形式)、パスワード(必須、8文字以上、数字・英字両方含む)、パスワードの確認(必須、パスワードと同一)フィールドが含まれます。
registerについて
registerを用いることで、フォーム送信での値の制御を簡潔に書くことができます。
以下のコードでは、input入力した値をtest
として送信することができます。
nameは1フォーム内で一意である必要があります。
<form>
<input {...register("test")} />
</form>
// => `{test: 'value'} `として送信される
また様々なオプションを使うことでバリデーション等を設定することができます。
以下のコードでは、例としてuserName
に入力する値が、「入力必須であること」「10文字以上であること」のバリデーションを設定しています。
<form>
<input
{...register("userName", {
required: true,
minLength: 10
})}
id="userName"
className="formArea"
/>
</form>
handleSubmitについて
handleSubmitを用いることで、フォーム送信時の挙動を簡潔に書くことができます。
以下のコードでは、formタグにonSubmit={handleSubmit(onSubmit)}
を付与することで、送信ボタンを押した際に、予め設定しておいたonSubmit
内が実行されます。
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("test")} />
<input type="submit" />
</form>
// => '送信'をクリックするとonSubmit内が実行
以上を用いて作成したフォームが以下になります。
2.データ編集の実装
既存のユーザーデータ(ユーザー名、メールアドレス、自己紹介文)を編集できるフォームを作成します。フォームロード時にこれらのフィールドに既存のデータをプリフィルします。
送信時にlocalStorageに保存し、再読み込みした時に保存した値がフォームに入力されるように実装してみます。
getValuesについて
getValuesを用いることで、フォームに入力された値を簡単に取得することができます。
以下のコードでは、'kagunyan'と入力して送信ボタンをクリックしたとき、getValue()
を用いることで{ userName: "kagunyan" }
を取得することができます。
const onSubmit = () => {
const profile = JSON.stringify(getValues());
localStorage.setItem("userProfile", profile);
// { userName: "kagunyan" }をlocalStorageに保存
};
// ~~~
return(
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("userName")} />
<input type="submit" />
</form>
);
setValueについて
setValueを用いることで、値を任意のフォームに簡単に渡すことができます。
以下のコードでは、setValue("userName", data.userName)
と書くことで、userName
というフォームに対してdata.userName
の値を渡すことができます。
useEffect(() => {
const profile = localStorage.getItem("userProfile");
if (profile !== null) {
const data = JSON.parse(profile);
setValue("userName", data.userName);
} else {
// localStorageに何も保存されてないとき用のmock
setValue("userName", mock.userName);
}
}, []);
以上を用いて作成したフォームが以下になります。
3.フォーム配列の使用
ユーザーが複数のホビーやスキルを入力できるフォームを作成します。各フィールドには"ホビー/スキル名"と"経験レベル"の二つの入力欄があります。
複数の項目を追加/削除できるようなフィールドを作りたい時に便利なのが、useFieldArray
です。
useFieldArray
を使うことによって、フィールド内の配列を簡単に記述でき、扱うことができます。
const { fields, append, remove } = useFieldArray({
control,
name: "test"
});
fieldsについて
useFieldArrayでは、複数のinput要素をfieldsとして管理します。
例えば"ホビー/スキル名"と"経験レベル"の2つの値がある場合、下記のように書くことができます。
{fields.map((field, index) => {
return (
<div className="signupForm" key={field.id}>
{index}
<br />
<label htmlFor="name">ホビー/スキル名</label>
<input
{...register(`test.${index}.name`, { minLength: 1 })}
id="name"
className="formArea"
/>
<label htmlFor="level">経験レベル</label>
<input
{...register(`test.${index}.level`, { minLength: 1 })}
id="level"
className="formArea"
defaultValue={data?.userName}
/>
<p className="errorText"></p>
<button type="button" onClick={() => remove(index)}>
削除
</button>
</div>
);
})}
appendについて
フィールドの最後に新たにinput要素を追加します。
<button type="button" onClick={() => append({ name: "", level: 0 })}>
追加
</button>
removeについて
フィールド内の特定のinputを削除します。
remove(index)
のように書くことで、指定したindexを持つinputを削除することができます。
{fields.map((field, index) => {
return (
<div className="signupForm" key={field.id}>
<input key={field.id}/>
<button type="button" onClick={() => remove(index)}>
削除
</button>
</div>
);
})}
以上を用いて作成したフォームが以下になります。
4.エラーメッセージの表示
ユーザーがフォームを正しく入力しなかった場合にエラーメッセージを表示します。各フィールドの下にエラーメッセージを表示し、フィールドのボーダーを赤に変更します。
formStateについて
ここではエラーを表示するため、formStateのerrorsについてまとめます。
const { formState: { errors } } = useForm();
formStateのerrorsを使うことで、任意のフォームがバリデーションエラーの場合などに非同期でエラーメッセージを表示させることができます。
以下のコードでは、userName
が未入力または10文字未満だった場合に「正しいユーザ名を入力してください」とエラーメッセージが表示させることができます。
<div className="signupForm">
<label htmlFor="userName">ユーザ名</label>
<input
{...register("userName", {
minLength: 10
})}
id="userName"
className="formArea"
/>
<p className="errorText">
{errors.userName && "正しいユーザ名を入力してください"}
</p>
</div>
5.フォームのリセット
フォーム下部に"リセット"ボタンを設置し、このボタンが押されたら全フィールドを初期状態に戻します。
resetについて
ボタンにonClick={() => reset()}
を付与することで簡単に作成することができます。
<input
type="button"
onClick={() => reset()}
/>
以上を用いて1で作成したものにリセットボタンを追加したフォームが以下になります。
最後に
- react-hook-formの基礎的な知識を知ることで、業務内で扱うコードを読むことや、フォームに関する機能を実装することがやりやすくなりました。
- 今後もまとめていきます。
Discussion