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なりのエラー表記と繋げるだけでバリデーション機能完成です。