CodeZine(コードジン)

特集ページ一覧

フォームのバリデーションに役立つYupとは? React向けライブラリを解説

現場で役立つ! React向けライブラリ詳説 第2回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2021/02/12 11:00
目次

7つのデータ型

 Yupは入力項目の特性を宣言的に記載することでスキーマを組み立て、バリデーション処理を実施できるライブラリだということをここまでに解説しました。次は、Yupでどんなデータをバリデーションできるのかを見ていきましょう。Yupが取り扱うデータ型は、大別すると7つに分類できます。

  • mixed:共通データ型
  • string:文字列型
  • number:数値型
  • boolean:真偽値型
  • date:日付型
  • array:配列型
  • object:オブジェクト型

 共通データ型ジャンルの関数群だけは少し特殊で、どんなデータ型にも当てはまるrequired()関数などが当てはまります。他のデータ型については「本当にそのデータ型の値が入力されたか」がチェックされ、その上で「大きい、小さい」「長い、短い」などの条件がチェックされることになります。それでは、フォーム実装でよく使う項目を中心に、どんな条件付けができるのかを見ていきましょう。

mixed:共通データ型

 mixed()でスキーマを作った場合、その項目はすべてのデータ型を受け入れます。例えば、リスト5のようにundefinedを入力値として渡しても、バリデーションが成功します。

[リスト5]mixedはどんなデータ型でも受け入れる
const schema = yup.mixed();

schema.isValid(undefined, function (valid) {
  valid; // => true
});

 何らかの理由で複雑なデータ型をフォームで扱うことになり、データ型のチェックをしたくない場合にmixed()を利用するとよいでしょう。またmixed()に付けられるバリデーション条件は、他のすべてのデータ型に同じものを定義できるので、汎用性が高いものになっています。

  • required():必須項目である
  • default(any):入力値がない場合のデフォルト値を指定する
  • oneOf(array):複数の項目のうちどれか1つならばOK

 required()は、これまでの解説にも出てきた通り、フォームのUIに頻出する必須項目を扱います。default()は、入力項目がundefinedだった場合にデフォルト値を割り当てるために利用します。validate()関数が成功したときに渡される値は元の入力値そのままではなく、このdefault()で割り当てた値で置き換えることもできるということです。oneOf()は、事前に定義した1つまたは複数の値に入力値が含まれているかをチェックする、少しユニークな条件です。リスト6のように使います。

[リスト6]oneOf
const schema = yup.mixed().oneOf(['jiro', 10]); // (1)

await schema.isValid(10); // => true // (2)
await schema.isValid('jiro'); // => true // (3)
await schema.isValid(new Date()); // => false // (4)

 (2)と(3)の値は(1)の配列に含まれているので、バリデーションで正常と判定されます。一方、(4)はDate型の値なのでエラー扱いとなります。ドロップダウンなどの選択式のUIで、入力値の候補がいくつかに絞られる場合には、有効な選択肢となるでしょう。

string:文字列型

 string()で作ったスキーマは入力値を文字列としてチェックします。文字列は入力フォームにとって最も基本的なデータ型なので、チェック項目も多様です(リスト7)。

[リスト7]stringに指定できる条件
// 文字列ならOK
await yup.string().isValid('こんにちは'); // => true
// 必須入力
await yup.string().required().isValid('hi'); // => true
// 必須入力の場合に空文字は不正となる
await yup.string().required().isValid(''); // => false
// 指定した文字数以外だとエラー
await yup.string()
  .length(5, '入力値は5文字ちょうどで入力してください').isValid('aaaaaa'); // => false
// 指定した最小文字数より小さいとエラー
await yup.string()
  .min(5, '入力値は5文字以上にしてください').isValid('aaa'); // => false
// 指定した最大文字数より大きいとエラー
await yup.string()
  .max(5, '入力値は5文字以下にしてください').isValid('aaa'); // => true
// 正規表現にマッチしなければエラー
await yup.string().matches(/(dog|cat)/).isValid('bird'); // => false
// メールアドレスの仕様に沿っていなければエラー
await yup.string().email().isValid('aaaa@example.com'); // => true
// URLの仕様に沿っていなければエラー
await yup.string().url().isValid('https://example.com'); // => true

 入力文字数に関するバリデーションは特に重宝するので、覚えておくとよいでしょう。

number:数値型

 number()で作ったスキーマは入力値を数値としてチェックします(リスト8)。

[リスト8]numberに指定できる条件
// 数値ならOK
await yup.number().isValid(10); // => true
// 指定した最小値より小さいとエラー
await yup.number().min(5).isValid(3); // => false
// 指定した最大値より大きいとエラー
await yup.number().max(5).isValid(5); // => true
// 指定した最大値以上だとエラー
await yup.number().lessThan(5).isValid(5); // => false
await yup.number().lessThan(5).isValid(4); // => true
// 指定した最小値以下だとエラー
await yup.number().moreThan(5).isValid(5); // => false
await yup.number().moreThan(5).isValid(6); // => true
// 正の値ならOK
await yup.number().positive().isValid(5); // => true
// 負の値ならOK
await yup.number().negative().isValid(-5); // => true
// 整数ならOK
await yup.number().integer().isValid(1.1); // => false

 数値の境界値チェックに便利な条件が整備されていますね。

boolean:真偽値型

 boolean()で作ったスキーマは入力値を真偽値としてチェックします(リスト9)。

[リスト9]booleanに指定できる条件
// 真偽値ならOK
await yup.boolean().isValid(true); // => true

 boolean()は2値しかないので、バリデーションルールは特に整備されていません。

date:日付型

 date()で作ったスキーマは入力値を日付型としてチェックします(リスト10)。

[リスト10]dateに指定できる条件
// Date型ならOK
await yup.date().isValid(new Date()); // => true
// ISO8601形式の文字列でもOK
await yup.date().isValid('2020-12-24T03:17Z'); // => true
// 指定した日付以降ならOK
await yup.date().min('2020-12-23').isValid('2020-12-24'); // => true
// 指定した日付以前ならOK
await yup.date().max('2020-12-23').isValid('2020-12-22'); // => true

 日時の範囲を指定できるのは便利ですね。

array:配列型

 array()で作ったスキーマは配列で渡された入力値の集合についてチェックします(リスト11)。

[リスト11]arrayに指定できる条件
// 配列ならOK
await yup.array().isValid([1, 2]); // => true
// 他のデータ型で縛ることもできる
await yup.array(yup.string()).isValid(['a', 'b']); // => true
await yup.array(yup.string()).isValid([1, 2]); // => false
// 配列が指定した長さではない場合にエラー
await yup.array().length(5).isValid([1, 2]); // => false
// 配列が指定した長さより小さい場合にエラー
await yup.array().min(5).isValid([1, 2]); // => false
// 配列が指定した長さより大きい場合にエラー
await yup.array().max(5).isValid([1, 2]); // => true
// 配列内の値もチェックできる
await yup
  .array(yup.number().min(2)).isValid([1, 2]); // => false (2より小さい数値が含まれているため)

 複数回答を許可しているフォームなどで威力を発揮する機能ですね。

object:オブジェクト型

 object()で作ったスキーマはオブジェクトで渡された入力値の集合についてチェックします。Formikをはじめとして、フォームの入力値をデータとして表現する場合にはオブジェクトの形になることが多いため、スキーマの最上位のデータ型として重宝します(リスト12)。

[リスト12]objectでデータ構造を定義する
// shapeで項目ごとのチェック条件を定義できる
yup.object().shape({
  name: yup.string().required(),
  age: yup.number().required().positive().integer(),
  email: yup.string().email(),
});

 オブジェクトで最上位のデータ構造を定義し、個別のデータ構造はstring()number()で定義するのがよくあるスタイルになります。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:現場で役立つ! React向けライブラリ詳説

著者プロフィール

  • WINGSプロジェクト 中川幸哉(ナカガワユキヤ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5