グローバルナビゲーションへ

本文へ

フッターへ

お役立ち情報Blog



React Hook Form(V7)を使って簡単にバリデーションを実装しよう!

現在担当しているプロジェクトで、フロントエンドのバリデーションを実装することとなり「React Hook Form」を採用しました。
Version7 が最近出たばかりであまり情報が出回っておらずつまずいたので使い方や仕様について紹介していきます。

コードは React と Typescript を使用します。

React Hook Form とは

React Hook Form とは「高性能で柔軟かつ拡張可能な使いやすいフォームバリデーションライブラリ」を掲げた入力フォームの管理に特化した React 向けのライブラリです。
状態管理を DOM で行う非制御コンポーネントでフォームの値を扱うことで他よりも高速なフォームライブラリを可能にしています。

ほかのフォームライブラリとの比較

React Hook Form のインストール

npm install react-hook-form

[基本編]バリデーション

3 つの入力エリアに、異なる下記条件のバリデーションをかけた例です。

  1. 必須
  2. 5文字以上の文字列
  3. 10以下の数字

実際はこのような動きになります。

コードは下記のようになります。

type Input = {
  required: string;
  maxLength: string;
  maxNumber: number;
};

const App = (): JSX.Element => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Input>({
    criteriaMode: "all",
    shouldFocusError: false,
  });

  const onSubmit: SubmitHandler<Input> = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      trueの場合必須 
      <br />
      <input {...register("required", { required: true })} />
      {errors.required && "文字が入力されていません"}
      <br />
      5文字以上の文字列
      <br />
      <input {...register("maxLength", { maxLength: 5 })} />
      {errors.maxLength && "5文字以上が入力されています"}
      <br />
      10以内ならOK
      <br />
      <input type="number" {...register("maxNumber", { max: 10 })} />
      {errors.maxNumber && "10以上の数字が入力されています"}
      <br />
      <input type="submit" />
    </form>
  );
};

上から順番に見ていきましょう。

まず最初に useForm で初期化します。

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Input>({
    criteriaMode: "all",
    shouldFocusError: false,
  });

useForm から各メソッドを受け取っています。

  • register : 入力または選択された要素を登録し検証します
  • handleSubmit : 検証が成功するとフォーム内のデータを受け取ります
  • formState: { errors } : バリデーションエラーを受け取ります

useForm の引数にオプションを設定できます。

  • criteriaMode
    • firstError(default) : 上から順番に検証され最初のエラーが返されます
    • all : 全てのエラーが返されます
  • shouldFocusError
    • true : 最初のエラーがフォーカスされます
    • false : フォーカスされなくなります

検証用に handleSubmit で返された値をコンソールに表示しています。

const onSubmit: SubmitHandler<Input> = (data) => console.log(data);

// handleSubmitの引数に使われています。
<form onSubmit={handleSubmit(onSubmit)}>

input に入力した値が register に登録された検証内容で検証されます。

<input {...register("required", { required: true })} />
<input {...register("maxLength", { maxLength: 5 })} />
<input type="number" {...register("maxNumber", { max: 10 })} />

register でエラーが発生した場合、その register に設定した key で error から取り出すことができます。{error.key}
エラーが存在しているかどうかでエラーメッセージを表示しています。

{errors.required && "文字が入力されていません"}
{errors.maxLength && "5文字以上が入力されています"}
{errors.maxNumber && "10より大きい値の数字が入力されています"}

[応用編]バリデーション

type Input = {
  conditions: string;
};

const App = (): JSX.Element => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Input>({
    mode: "onChange",
    criteriaMode: "all",
    shouldFocusError: false,
  });

  const onSubmit: SubmitHandler<Input> = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      必須&5文字以下&A-Zの文字列
      <br />
      <input
        {...register("conditions", {
          required: true,
          maxLength: 5,
          pattern: /[A-Z]/,
        })}
      />
      <br />
      {errors.conditions?.types?.required && "文字が入力されていません"}
      {errors.conditions?.types?.maxLength && "5文字以上が入力されています"}
      {errors.conditions?.types?.pattern && "A-Z以外の文字が含まれています"}
      <br />
      <input type="submit" />
    </form>
  );
};

基本編との違いは

  • submit を押さなくても onChange でバリデーションが行われる
  • 一つのフォームで条件を3つに増やしそれぞれ複数のエラーを表示させる

というところです。下記のような動きになります。

実際に変更されたコードを見ていきましょう。

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Input>({
    mode: "onChange",
    criteriaMode: "all",
    shouldFocusError: false,
  });

mode: “onChange”を追加しました。
このようにすることで submit を押さなくてもエラーが表示されるのでリアクティブな感じに実装できます。

<input
  {...register("conditions", {
    required: true,
    maxLength: 5,
    pattern: /[A-Z]/,
  })}
/>
<br />
{errors.conditions?.types?.required && "文字が入力されていません"}
{errors.conditions?.types?.maxLength && "5文字以上が入力されています"}
{errors.conditions?.types?.pattern && "A-Z以外の文字が含まれています"}

上記の実装は一つのフォームで複数の条件とその条件に対応したエラーを表示させるというものです。
types でどの条件のエラーかを判別することができます。

さいごに

2パターンのバリデーションを実装してみました。 他にもさまざまなバリデーションに対応できるように、多くのメソッドが実装されていて拡張性の高いフォームライブラリとなっています。Formik や ReduxForm に比べると新しいライブラリで日本語の記事が少ないこともありますが、勢いのあるライブラリだと思います。 ぜひ使ってみてはいかがでしょうか。

この記事を書いた人

アーティス
アーティス
創造性を最大限に発揮するとともに、インターネットに代表されるITを活用し、みんなの生活が便利で、豊かで、楽しいものになるようなサービスやコンテンツを考え、創り出し提供しています。
この記事のカテゴリ

FOLLOW US

最新の情報をお届けします