🔍

React useFormを利用してformを作成する

2022/04/23に公開

React Hook Form

Reactでフォームを作るとき、フォームごとuseStateで入力値を管理したり、フォームのバリデーションを直接書いたりしてかなり大変です。

その時利用できるのがReact Hook FormのuseFormです。
今回は以下のサンプルで使った部分だけ絞って説明したいと思います。サンプルのデザインにはtailwind CSSを利用しています

ソースコード
https://github.com/copetit/redpanda-nextjs/blob/main/pages/login.tsx

公式ドキュメント
https://react-hook-form.com/jp/
https://react-hook-form.com/api/useform

インストール

$ npm install react-hook-form

// react18利用中にDependancyエラーの場合
// react18の場合まだ使えないため、後ろに --legacy-peer-deps をつけてインストールします
$ npm install react-hook-form --legacy-peer-deps

インストールできたらimportして利用できます。

import { useForm } from "react-hook-form";

useFormについて

// formで利用する値のtype指定
interface LoginForm {
  email: string;
  password: string;
}

// 利用するメソッドを定義しています。ここの今回メソッドを以下で説明します。
const {
  register,
  watch,
  handleSubmit,
  formState: { errors },
} = useForm<LoginForm>();

method

register

フォームから入力された値のstate管理、バリデーション処理が可能です。
以下のソースコードではemailフォームの値を受け取り、項目入力必須のバリデーション処理を書いています。

<div className="flex w-full flex-col">
<label className="text-sm text-gray-800" htmlFor="email">
  Email
</label>
<input
  {...register("email", { required: "emailを入力してください" })}
  className="rounded-md border px-3 py-2 focus:border-2 focus:border-teal-500 focus:outline-none"
  type="email"
  name="email"
/>
</div>

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

watch

フォームの値変更の監視ができます。ドキュメントにはチェックボックスにチェックをつけるとフォームを表示させる例が乗っていました。
https://react-hook-form.com/api/useform/watch

handleSubmit

フォームをsubmitした時の処理をかけます。handleSubmit()は引数を二つ受け取ります。
引数1はバリデーション処理がOKの場合の関数、引数2はバリデーション処理がNGの場合に呼ばれる関数が入ります。

以下のソースコードだとpasswordがバリデーション失敗した時に、このようにconsole.logされます。

// バリデーション処理がOKの場合に呼ばれる関数
const isValid = (data: LoginForm) => {
  console.log(data);
};

// バリデーション処理がNGの場合に呼ばれる関数
const isInValid = (erros: any) => {
  console.log(errors);
  console.log("Fail Login");
};

<form onSubmit={handleSubmit(isValid, isInValid)} className="flex w-full  flex-col items-center space-y-5 ">
  //省略
</form>

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

formState

フォームの状態をobjectで管理しています。
formState: { errors, isDirty, isSubmitting, touchedFields, submitCount }
いろんな状態を使えますがここでは一番利用するerrorsだけ説明します。
フォームでエラーになった場合、errors.[項目名]にエラーのobjectが入ります。{errors.password?.message} のように書くと画面上でフォームのエラーメッセージを表示できます。

<input
{...register("password", {
  required: "passwordを入力してください",
  minLength: { value: 8, message: "8文字以上入力してください" },
})}
className="rounded-md border px-3 py-2 focus:border-2 focus:border-teal-500 focus:outline-none"
type="password"
name="password"
/>
<div className="mt-1 font-semibold text-rose-500">
  {errors.password?.message}
</div>

https://react-hook-form.com/api/useform/formstate

Props

今回はデフォルトのonSubmitだったため、ソースコード上にはありません。
useForm自体にも様々なpropsを受け取ってカスタマイズできます。

useForm({
  mode: 'onSubmit',
  reValidateMode: 'onChange',
  defaultValues: {},
  resolver: undefined,
  context: undefined,
  criteriaMode: "firstError",
  shouldFocusError: true,
  shouldUnregister: false,
  shouldUseNativeValidation: false,
  delayError: undefined
})

その中で modeですが、バリデーションチェックをするタイミングの指定ができます。
onSubmit
デフォルトはonSubmitです。submitした時にエラーが表示されます。
onChange
入力時に検知してエラーが表示されます。
onBlur
inputの外をクリックした時にエラーが表示されます。onBlubのサンプルです。

const {
  register,
  watch,
  handleSubmit,
  formState: { errors },
} = useForm<LoginForm>();

https://react-hook-form.com/api/useform

まとめ

useFormを利用すると、かなり簡単にフォームを完成することができます。
またドキュメントにもバリデーションサンプルなど親切に書いてあるので、使う時にはぜひ読んでみてください。

Discussion