【React】React Hook Form と yup でフォームのバリデーションを作る

 React Hook Form は Reack のバリデーションライブラリの一つです。 Hook の名が示す通り関数コンポーネントの Hook 機能を使ってバリデーション用のモジュールを提供してくれます。
ホーム | React Hook Form – Simple React forms validation
 yup はバリデーションルールを定義するためのライブラリです。メソッドチェーン的にルールを決定できます。
 React Hook Form と yup を組み合わせることでフォームのバリデーション定義を分かりやすく作れます。デモは次です。
はじめる | React Hook Form – Simple React forms validation#スキーマバリデーション

 これは次の記述で実現されています。

import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from '@hookform/resolvers';
import * as yup from "yup";

// yup によるバリデーションルール定義
// schema の名らしく一構造体にまとめて記述できる
const schema = yup.object().shape({
  firstName: yup.string().required(),
  age: yup.number().positive().integer().required(),
});

export default function App() {

  // バリデーション機能を呼び出し
  //  yupResolver(schema) で上述の yup ルールを採用
  const { register, handleSubmit, errors } = useForm({
    resolver: yupResolver(schema)
  });
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* ref={register} でバリデーション機能に登録されます */}
      <input type="text" name="firstName" ref={register} />
      {/* errors はバリデーションエラー内容を持つ構造体で自動で更新されます */}
      <p>{errors.firstName?.message}</p>
        
      <input type="text" name="age" ref={register} />
      <p>{errors.age?.message}</p>
      
      <input type="submit" />
    </form>
  );
}

 シンプルで読みやすく書きやすいです。例だけでもバリデーションとしては十分ですが日本語に対応できていません。日本語に対応したデモが次です。

 これは次の様なコードで実現しています。

/*** LocaleJP.js ***/
// 日本語のルールと文言の対応を定義
export const LocaleJP = {
  mixed: {
    default: '${path}は無効です',
    required: '${path}は必須フィールドです',
    oneOf: '${path}は次の値のいずれかでなければなりません:${values}',
    notOneOf: '${path}は次の値のいずれかであってはなりません:${values}',
  },
  string: {
    length: '${path}は正確に${length}文字でなければなりません',
    min: '${path}は少なくとも${min}文字でなければなりません',
    max: '${path}は最大${max}文字でなければなりません',
    matches: '${path}は次と一致する必要があります: "${regex}"',
    email: '${path}はメールアドレス形式である必要があります',
    url: '${path}は有効なURLでなければなりません',
    trim: '${path}はトリミングされた文字列でなければなりません',
    lowercase: '${path}は小文字の文字列でなければなりません',
    uppercase: '${path}は大文字の文字列でなければなりません',
  },
  number: {
    min: '${path}は${min}以上である必要があります',
    max: '${path}は${max}以下でなければなりません',
    lessThan: '${path}は${less}より小さくなければなりません',
    moreThan: '${path}は${more}より大きくなければなりません',
    notEqual: '${path}は${notEqual}と等しくない必要があります',
    positive: '${path}は正の数でなければなりません',
    negative: '${path}は負の数でなければなりません',
    integer: '${path}は整数でなければなりません',
  },
  date: {
    min: '${path}フィールドは${min}より後でなければなりません',
    max: '${path}フィールドは${max}より前でなければなりません',
  },
  object: {
    noUnknown: '${path}フィールドには,オブジェクトシェイプで指定されていないキーを含めることはできません',
  },
  array: {
    min: '${path}フィールドには少なくとも${min}の項目が必要です',
    max: '${path}フィールドには${max}以下の項目が必要です',
  },
};

/*** BaseYup.js ***/
import { LocaleJP } from '@/validation/LocaleJP';
import * as yup from 'yup';

// yup に作った日本語メッセージを定義
yup.setLocale(LocaleJP);
// yup は import する度に setLocale する必要があるので setLocale 済みの yup を呼び出せるように export
export const BaseYup = yup;


/*** form.jsx ***/
// 上述の BaseYup を仕様
import { BaseYup } from "./BaseYup";


// スキーマの末尾に label と付けてフィールドごとの自然言語名を定義
const SignupSchema = BaseYup.object().shape({
  firstName: BaseYup.string().required().label("名"),
  lastName: BaseYup.string().label("姓"),
  age: BaseYup.number().required().positive().integer().label("年齢"),
  website: BaseYup.string().url().label("WebサイトURL")
});

 例では基本ルールのみでしたが yup は任意の関数とメッセージによるカスタムルールにも対応しています。こんな感じで React Hook Form と yup によってあっという間にバリデーション用のロジックを作れます。ロジックを作ったならばあとはデザインフレームワークなり手製のCSSなりのエラー表記と繋げるだけでバリデーション機能完成です。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG