🐣

React-Hook-Formのおさらい

2023/08/23に公開

はじめに

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>

https://react-hook-form.com/docs/useform/register

handleSubmitについて

handleSubmitを用いることで、フォーム送信時の挙動を簡潔に書くことができます。
以下のコードでは、formタグにonSubmit={handleSubmit(onSubmit)}を付与することで、送信ボタンを押した際に、予め設定しておいたonSubmit内が実行されます。

<form onSubmit={handleSubmit(onSubmit)}> 
  <input {...register("test")} />
  <input type="submit" />
</form>
// => '送信'をクリックするとonSubmit内が実行

https://react-hook-form.com/docs/useform/handlesubmit

以上を用いて作成したフォームが以下になります。

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>
);

https://react-hook-form.com/docs/useform/getvalues

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);
  }
}, []);

https://react-hook-form.com/docs/useform/setvalue

以上を用いて作成したフォームが以下になります。

3.フォーム配列の使用

ユーザーが複数のホビーやスキルを入力できるフォームを作成します。各フィールドには"ホビー/スキル名"と"経験レベル"の二つの入力欄があります。

複数の項目を追加/削除できるようなフィールドを作りたい時に便利なのが、useFieldArrayです。
useFieldArrayを使うことによって、フィールド内の配列を簡単に記述でき、扱うことができます。

const { fields, append, remove } = useFieldArray({
  control,
  name: "test"
});

https://react-hook-form.com/docs/usefieldarray

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()}
/>

https://react-hook-form.com/docs/useform/reset

以上を用いて1で作成したものにリセットボタンを追加したフォームが以下になります。

最後に

  • react-hook-formの基礎的な知識を知ることで、業務内で扱うコードを読むことや、フォームに関する機能を実装することがやりやすくなりました。
  • 今後もまとめていきます。

Discussion