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#スキーマバリデーション
【React】React Hook Form と yup でフォームのバリデーションを作る – 株式会社シーポイントラボ | 浜松のシステム・RTK-GNSS開発
これらの組み込みのルールでもそれなりのバリデーションができるのですが、作りこむとなるととても足りません。ルールを作り、yup に増やす必要があります。これは次のコードで実現できます。
/** rules/password.js ルール定義関数を記述したファイル */
// パスワード強度調査ライブラリ zxcvbn
// @see https://github.com/dropbox/zxcvbn
import * as zxcvbn from 'zxcvbn';
import {ValidationError, TestContext, } from 'yup';
// 与えられたパスワードに要求する zxcvbn でスコア化された強度の最低値
const ZXCVBN_SCORE_REQUIRE_MIN = 2;
/**
* パスワードルール
* @param password
* @return {true|ValidationError}
*/
export const passwordZxcvbnRule = function (password) {
// この中での this は TestContext
// zxcvbn を実行して強度チェック
const res = zxcvbn(password);
// スコアが定数以上ならば true
return res.score >= ZXCVBN_SCORE_REQUIRE_MIN
? true
// スコアが定数を下回った場合、yup 用のエラーオブジェクトを生成して返す
: this.createError({message: res.feedback.suggestions[0],})
// this.createError: (params?: { path?: string; message?: string; params?: object }) => ValidationError;
// 未定義部はルール適用先でよしなにしてくれます
}
/** BaseYup.js プロジェクト用に改造した yup を export するファイル*/
import * as yup from 'yup';
import { passwordZxcvbnRule } from './rules/password';
// rules/password.js で定義したルールを zxcvbn と名付けて yup に追加
yup.addMethod(yup.string, 'zxcvbn', function() {
return this.test('zxcvbn', '',passwordZxcvbnRule);
});
export const BaseYup = yup;
/** form.jsx yup を使うフォーム */
import { BaseYup as yup } from '../validation/BaseYup';
import {useForm} from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers';
const schema = yup.object().shape({
// zxcvbn ルールを使うと宣言
password: yup.string().required().zxcvbn().label('パスワード'),
});
export const PasswordForm = () => {
const { register, handleSubmit, errors, getValues, setError } = useForm({
resolver: yupResolver(schema),
defaultValues: {password:''},
});
const onSend = handleSubmit(() => {
Object.keys(errors).length === 0 && パスワードをどこかに送る関数();
});
return (
<div>
<label>パスワード</label>
<input
type='text'
name='password'
inputRef={register}
/>
<span>{errors.password?.message}</span>
</div>
);
}
こんな感じで、与えられた入力値を元に true|ValidationError を返す関数を yup.addMethod すると addMethod で定義した名前でルールを定義できます。この様にすると次の様なプログラムを動かせます。

複雑なルールの場合、エラーメッセージも複雑になりがちです。そういった際、ルール単位で処理を構築できる addMethod は程々の粒度で便利です。