Open4

React Hook Form の導入

はらまきはらまき

基本的な使い方(JS)

  • まずは先にJSでの基本を抑えておく
    • useForm
    • register
    • handleSubmit

example.js
import { useForm } from "react-hook-form"


export default function App() {
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm()


  const onSubmit = (data) => console.log(data)


  console.log(watch("example")) // watch input value by passing the name of it


  return (
    /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register("example")} />


      {/* include validation with required or other standard HTML validation rules */}
      <input {...register("exampleRequired", { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}


      <input type="submit" />
    </form>
  )
}

"react-hook-form"のimport

  • まずはimportを行う
import { useForm } from "react-hook-form"

カスタムフックuseForm()から個々の関数を読み込む

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

submit時の関数を用意

  • handleSubmit():フォーム送信時にバリデーションを実行し、成功時にデータを処理。
  • submit時に実行される関数にhandleSubmit()指定し、その関数の引数にユーザーが定義した関数(onSubmit())を指定してやる
const onSubmit = (data) => console.log(data)
...
  return (
    /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
    <form onSubmit={handleSubmit(onSubmit)}>
...

register関数

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


export default function App() {
  const { register, handleSubmit } = useForm()
  const onSubmit = (data) => console.log(data)


  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName", { required: true, maxLength: 20 })} />
      <input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} />
      <input type="number" {...register("age", { min: 18, max: 99 })} />
      <input type="submit" />
    </form>
  )
}
  • register: 各入力フィールドをフォームに登録し、バリデーションルールを設定する。
  • バリデーションの設定方法:
    • registerの第2引数に指定する
    • <input {...register("exampleRequired", { required: true })} />
  • バリデーションの種類:

エラー処理

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

const BasicForm = () => {
  const { register, handleSubmit, formState: { errors } } = useForm();

  const onSubmit = (data) => {
    console.log("フォームデータ:", data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* 名の入力フィールド */}
      <div>
        <label htmlFor="firstName"></label>
        <input
          id="firstName"
          {...register("firstName", { required: "名は必須です。" })}
          aria-invalid={errors.firstName ? "true" : "false"}
        />
        {errors.firstName && (
          <span role="alert" style={{ color: "red" }}>
            {errors.firstName.message}
          </span>
        )}
      </div>

      {/* メールアドレスの入力フィールド */}
      <div>
        <label htmlFor="email">メールアドレス</label>
        <input
          id="email"
          type="email"
          {...register("email", {
            required: "メールアドレスは必須です。",
            pattern: {
              value: /^\S+@\S+$/i,
              message: "有効なメールアドレスを入力してください。",
            },
          })}
          aria-invalid={errors.email ? "true" : "false"}
        />
        {errors.email && (
          <span role="alert" style={{ color: "red" }}>
            {errors.email.message}
          </span>
        )}
      </div>

      {/* 送信ボタン */}
      <button type="submit">送信</button>
    </form>
  );
};

export default BasicForm;
  • const { register, handleSubmit, formState: { errors } } = useForm();
    • フォームのバリデーションエラーを含むオブジェクト(errors)を読み込む
  • formStateとは
    • formStateは、フォームの状態に関する情報を保持するオブジェクト
    • 主なプロパティには以下
      • isDirty: フォームが変更されたかどうかを示します。
      • isValid: フォームのバリデーションが成功しているかどうかを示します。
      • errors: フォームフィールドに関連するバリデーションエラーを保持します。
        • 各フィールド名をキーとして、そのフィールドに対応するエラー情報(メッセージやエラーレベルなど)が値として格納されます。
        • {
            "fieldName": {
              "type": "validationType",
              "message": "エラーメッセージ"
            },
            // 他のフィールド...
          }
          
        • fieldName: エラーが発生したフィールドの名前。
        • type: バリデーションの種類(例: required, minLength)。
        • message: エラーメッセージ。
  • オブジェクトの分割代入 (destructuring assignment)については以下を参照
はらまきはらまき

基本的な使い方(TS)

useFormにジェネリック型パラメータを指定する

  • useForm<T>()のように、ジェネリック型パラメータを指定することで、フォームの型構造を定義できる

SubmitHandler

  • SubmitHandlerは、React Hook FormをTypeScriptと共に使用する際に非常に役立つ型定義
  • 具体的には、フォームの送信時に呼び出される関数の型を定義するために使用される
  • これにより、フォームデータの型安全性を確保し、開発中のエラーを減らすことができる
  • 具体的な型定義は
type SubmitHandler<TFieldValues extends FieldValues> = (
  data: TFieldValues,
  event?: React.BaseSyntheticEvent
) => unknown | Promise<unknown>;
  • TFieldValuesは、フォームのフィールド値の型を表すジェネリック型パラメータです。
  • dataパラメータは、送信されたフォームデータを含むオブジェクトです。
  • eventパラメータは、フォーム送信イベントを表すオプションのパラメータです。
  • 戻り値の型はunknownまたはPromise<unknown>で、非同期処理も可能であることを示しています。
  • GitHub:https://github.com/react-hook-form/react-hook-form/blob/master/src/types/form.ts

サンプル

enum GenderEnum {
  female = "female",
  male = "male",
  other = "other",
}

interface IFormInput {
  firstName: string
  gender: GenderEnum
}
import ReactDOM from "react-dom"
import { useForm, SubmitHandler } from "react-hook-form"

enum GenderEnum {
  female = "female",
  male = "male",
  other = "other",
}

interface IFormInput {
  firstName: string
  gender: GenderEnum
}

export default function App() {
  const { register, handleSubmit } = useForm<IFormInput>()
  const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label>First Name</label>
      <input {...register("firstName")} />
      <label>Gender Selection</label>
      <select {...register("gender")}>
        <option value="female">female</option>
        <option value="male">male</option>
        <option value="other">other</option>
      </select>
      <input type="submit" />
    </form>
  )
}