Posted at

他の項目を利用して yup でバリデーションチェック(w/ formik)

More than 1 year has passed since last update.


はじめに

仕事でコミュニティが活発なライブラリを活用することが増えてきたのですが、日本語の記事がなかったり、英語の記事を見ながら試行錯誤したので、備忘も兼ねてまとめます。

同じ悩みを抱える人の救いになれば幸いです。

(間違いがあればご指摘ください)


Formik

Formik とは、Reactで使えるフォームの管理をしてくれるイケてるライブラリです。

同僚が使う理由として

"its the lib recommended by the formskit team"

を挙げていました。

ごめんなさい、ドヤ顔で言われてもそのすごさを理解できてないヘボヘボエンジニアです。

というか、Ant Design の Form Component であらかた入力フォームとバリデーション実装したタイミングだったので、「マジかよ…」と思いました。


yup

yup は、Yup is a JavaScript object schema validator and object parser.とあるように、 formik と連携してバリデーションチェックをしてくれるイケてるやつです。

formik のvalidationSchemaに yup のオブジェクトスキーマをセットしておけば、handleSubmitの際にチェックして、エラーだと onSubmit が呼び出されません。

余談ですが、yup のバリデーションを通過しているのに formik のprops.isValidの値が false になってることがありました。

yup はasync validationと書かれてるので、この辺りが原因?かもしれません。

props.isValidで判断することはやめて、真っ当にonSubmitに処理を書いてあげれば問題ないかと思います。


yup のバリデーション設定

本題に入ります。

他の項目とチェックしたいケースで一番用途が大きいのが確認用パスワードだと思います。

これはoneOfを利用すれば簡単に実装可能です。

import * as yup from 'yup';

/*** 中略 ***/

const validationSchema = yup.object().shape({
password: yup.string()
.required(),
passwordConfirmation: yup.string()
.oneOf([yup.ref('password')])
.required(),
});

次に、もうちょっとダイナミックに他の項目を使う方法ですが、下記の方法で実装可能です。

import * as yup from 'yup';

/*** 中略 ***/

const validationSchema = yup.object().shape({
optionalValue: yup.string()
.required(),
optionalDetail: yup.string()
.test('optionalDetail', 'otherValidation', function(value) {
if (this.parent.optionalValue === 'other' && value === undefined) {
return false;
}
return true;
}),
});

testのコールバック関数としてarrow functionを使うとthisが束縛されてしまうので、function()の形で記載します。


おわりに

初めての Qiita 投稿が少しニッチな内容になりました。

もっといい方法あるんじゃないか、あればぜひご紹介いただけると幸いです。