浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【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#スキーマバリデーション
【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 は程々の粒度で便利です。

  • この記事いいね! (0)