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