SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

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

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

  • X ポスト
  • このエントリーをはてなブックマークに追加

 前回に続いて、ブラウザアプリケーションの基本にして王道であるフォームを題材にします。今回は入力値のバリデーションを担当するライブラリとして、Yupについて解説します。入力欄1つひとつにバリデーションルールを定義する作業は、通常であれば面倒なものですが、Yupを使うとスッキリと定義できます。

  • X ポスト
  • このエントリーをはてなブックマークに追加

対象読者

  • JavaScriptとWeb開発の基礎に理解がある方
  • Reactを用いたJavaScriptアプリケーション開発の経験者

前提環境

 筆者の検証環境は以下の通りです。

  • macOS Big Sur 11.1
  • Node.js 15.5.0/npm 7.3.0
  • React 17.0.1
  • react-scripts 4.0.1
  • Formik 2.2.6
  • Yup 0.32.8

バリデーションを宣言的に記述する

 今回はフォームのバリデーションに役立つライブラリ、Yupについて解説します。前回解説した、フォーム作成補助ライブラリのFormikでは、入力内容のバリデーションをリスト1のように記述していました。

[リスト1]Formikの素直なバリデーション
<Formik
  validate={values => {
    const errors = {};
    if (!values.email) {
      errors.email = 'Eメールを入力してください'
    }
    return errors;
  }}
>

 validate属性の関数に、すべての入力欄の値が入ったオブジェクトであるvaluesが渡されるので、それの正否を判定し、もし誤りがあればvaluesオブジェクト内の項目名と同名のキーでerrorsオブジェクトにエラーメッセージを登録することになっていました。データに対してif文を駆使しながら1行ずつ処理を書いて判定してするので、いわゆる手続き的プログラミングの手法でバリデーションルールを実装することになります。

 UIの操作はReactのおかげで宣言的に記述できるようになっています。可能であれば、バリデーションルールの定義も宣言的プログラミングで行いたいですよね。そんな夢を叶えてくれるのが、Yupというバリデーション専門のライブラリです。Yupが生成するバリデーションルールはFormikでも公式サポートされているので、前回の内容と組み合わせることで、より快適にフォームを組み上げられることでしょう。

Yup

 YupはJason Quense氏が開発している、バリデーションのためのライブラリです。

図1:YupのGitHubリポジトリ
図1:YupのGitHubリポジトリ

 GitHubのREADME(説明書)には、Yupは"JavaScript schema builder for value parsing and validation"である、と書かれています。フォームの入力値を解析してバリデーションを行うために、JavaScriptでスキーマ(データ構造)を定義するためのライブラリである、ということです。ただ、スキーマと言われてもピンとこないと思うので、実際の例を見てみましょう。スキーマはリスト2のように、関数のチェーン呼び出しを組み合わせながら定義します。

[リスト2]スキーマを定義する
import * as yup from 'yup';

const schema = yup.object().shape({ // (1)
  name: yup.string().required(), // (2)
  age: yup.number().required().positive().integer(), // (3)
  email: yup.string().email(), // (4)
});

 (1)のyup.object()は、判定対象の入力値がオブジェクトで提供されることを期待する定義です。続いて、実際のデータ構造を.shape()で定義します。(2)はnameという項目が文字列型の必須項目であることを示しています。(3)はageという項目が数値型の必須項目であり、正の整数であることを期待する定義です。(4)はemailという項目が文字列型であり、メールアドレスとして正しい形式であることを期待する定義です。emailにはrequired()が付いていないので、任意入力の項目です。

 Yupのスキーマ定義は、このように各項目の特性を並べるだけで作成できます。バリデーションルールを宣言的に記述できる、魅力的なインターフェースですね。

 さて、本来はフォームに組み込んで使うライブラリですが、単独で動作させるためのインターフェースも用意されています。リスト2のスキーマを使って値を検証する場合は、リスト3のような書き方になります。

[リスト3]Yup単独でバリデーションを実行する
schema
  .isValid({ // (1)
    name: 'Taro',
    age: 24,
  })
  .then(function (valid) { // (2)
    // ...
  });

 Yupのスキーマオブジェクト(リスト2で作成したschema)には、データを検証するための関数として(1)のisValidが用意されています。スキーマの最上位のデータ型としてobject()を定義していたので、isValidに渡すデータもオブジェクトです。バリデーションは非同期で行われ、Promiseで返却されます。(2)のように.then()にコールバック関数を登録することで、入力値の正否をboolean型で受け取れるので、これを受けて次の処理を実施することになります。これがYupの最もシンプルな使い方です。

任意のエラーメッセージを扱う

 さて、ここまでの解説では、エラーメッセージを定義する場所も受け取る場所もありませんでした。エラーメッセージを受け取りたい場合は、isValid()の代わりにvalidate()を使います(リスト4)。

[リスト3]Yup単独でバリデーションを実行する
schema
  .validate({
    name: 'Taro',
    age: 'hi', // 数値型ではなく文字列型を渡している
  })
  .then(function (value) { // (1)
    // ...
  })
  .catch(function (err) { // (2)
    console.log(err.errors); // => ['age must be a number']
  });

 validate()を使った場合は、isValidのときと比べて挙動が変わります。成功した場合である(1)の.then()には、検証対象だった値(validate()の第一引数)がそのまま渡されます。一方、失敗した場合である(2)の.catch()には、エラーメッセージの配列が渡されます。ようやくここでエラーメッセージを見ることができました。

 エラーメッセージが英語で記載されているのが気になりますが、これはカスタマイズできます。スキーマを定義する時点で、各条件の関数に引数として文字列を渡すと、バリデーションエラーが起きたときにエラーメッセージとして利用されるのです(リスト4)。

[リスト4]エラーメッセージをカスタマイズする
import * as yup from 'yup';

const schema = yup.object().shape({
  name: yup.string().required('名前は必須項目です'),
  age: yup.number('年齢は数値で入力してください') // (1)
    .required('年齢は必須項目です')
    .positive('正の数を指定してください')
    .integer('整数で指定してください'),
  email: yup.string().email('メールアドレスの形式が不正です'),
});

schema
  .validate({
    name: 'Taro',
    age: 'hi', // 数値型ではなく文字列型を渡している
  })
  .catch(function (err) {
    console.log(err.errors); // => ['年齢は数値で入力してください'] // (2)
  });

 リスト2のスキーマ定義に少し手を加えて、各条件にメッセージを登録しました。(1)でageが数値ではなかった場合のメッセージを登録しています。これはリスト3の例と同様にエラーになり、(2)には(1)と同じ文字列がエラーメッセージとして渡されてきます。このように、日本語のエラーメッセージを扱うことも可能です。

 エラーメッセージを登録し忘れると、画面に英語のメッセージが出てくることになるので、業務で利用する場合には注意が必要かもしれません。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
7つのデータ型

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
現場で役立つ! React向けライブラリ詳説連載記事一覧

もっと読む

この記事の著者

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/13518 2021/02/12 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング