0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ReactHookForm(V7)でフォームの簡単バリデーション!(実装例&Gif付き)

Posted at

React と Typescript を使用します。

ReactHookForm とは

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

ReactHookForm のインストール

npm install react-hook-form

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

下記の条件で 3 つのフォームにバリデーションをかけた例です。

  • 必須
  • 5 文字以上の文字列
  • 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>
  );
};

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

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

まず最初に 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>
  );
};

react2.gif

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

基本編との違いは

  • 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 に比べると新しいライブラリで日本語の記事が少ないこともありますが、勢いのあるライブラリだと思います。
ぜひ使ってみてはいかがでしょうか。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?