#はじめに
今まで react-redux-form
を使ってたのですが、公式からもう使うなって言われてしまったのでFormik
に書き換えてみました。その際バリデーションのコントロールを行う為にYupをカスタマイズしたのでその内容をメモしておきます。Formik
での具体的なYup
の利用方法はここでは記載しません。
#カスタマイズの基本
import * as Yup from 'yup';
//カスタマイズを記述
export default Yup;
で、yup
を利用するときにはこのカスタマイズファイルを利用します。
import Yup from '/path/to/yup.custom.js';
#日本語化
公式サンプルだとTypeScript
なんですよね。
Yup.setLocale({
mixed: {
default: '入力エラーです',
required: '必須入力項目です',
oneOf: ({ values }) => `次の値のいずれかでなければなりません: ${values}`,
notOneOf: ({ values }) => `次の値のいずれかであってはなりません: ${values}`,
notType: '形式が違います',
},
string: {
length: ({ length }) => `${length}文字入力して下さい`,
min: ({ min }) => `${min}文字以上入力してください`,
max: ({ max }) => `${max}文字以内で入力して下さい`,
matches: '形式が違います',
email: '形式が違います',
url: '形式が違います',
trim: '前後にスペースを入れてはいけません',
lowercase: '小文字でなければなりません',
uppercase: '大文字でなければなりません',
},
number: {
min: ({ min }) => `${min}以上の値を入力して下さい`,
max: ({ max }) => `${max}以下の値を入力して下さい`,
lessThan: ({ lessThan }) => `${lessThan}より小さい値を入力して下さい`,
moreThan: ({ moreThan }) => `${moreThan}より大きい値を入力して下さい`,
notEqual: ({ notEqual }) => `${notEqual}と違う値を入力して下さい`,
positive: '正の数を入力して下さい',
negative: '負の数を入力して下さい',
integer: '整数を入力して下さい',
},
date: {
default: '形式が違います',
min: ({ min }) => `${min}以上の日付を入力して下さい`,
max: ({ max }) => `${max}以下の日付を入力して下さい`,
},
object: {
noUnknown: '有効なキーを持ったデータを入力して下さい',
},
array: {
min: ({ min }) => `${min}個以上の値を入力して下さい`,
max: ({ max }) => `${max}個以下の値を入力して下さい`,
},
});
引数として path
を取ると、例えば
length:({path,length}) =>`${path}には${length}文字入力して下さい`,
という記載ができるのですが、path
の値はそのままだと変数名ですので、label()
関数を使って
Yup.object().shape({
zipcode: Yup.string().label('郵便番号').length(7),
});
みたいな書き方が必要です。カスタマイズファイルの中でpath=>label
の変換なんかをしてみても面白そうです。
#独自メソッドの追加
addMethod()
とtest()
関数を使います。
Yup.addMethod(Yup.string, 'katakana', function() {
return this.test('katakana', 'カタカナで入力して下さい', function(value) {
if (value == null || value === '') return true;
return value.match(/^[ァ-ヶー ]+$/);
});
});
Yup.addMethod(Yup.string, 'unique', function(api) {
return this.test('unique', '既に使用されています', function(value) {
if (value == null || value === '') return true;
return new Promise(resolve => {
fetch(api + value).then(response => resolve(response.text === 'true'));
});
});
});
使うときは
Yup.string().katakana();
Yup.string().unique(apiPath);
のようになります。arrow function
を使うとthis
を上書きしてしまいますので
- this.path: 評価中の変数名
- this.from: Yupオブジェクトがネストされている場合、親の情報が取得できる
- this.createError(): 独自にエラーメッセージの作成ができる
等を利用したい場合は ()=>{}
では無くfunction(){}
を使いましょう。
addMethod()
で追加した関数にもsetLocaleが使えれば良かったのですが、駄目みたいです。
#変換について
このへんでも議論になっていますが、Formik で使う際に、Yup.cast()
や、 Yup.tranform()
による変換は基本的に動作しません。 自分はonSubmit
の時に独自に変換していますが、どうしても使いたければ formik-yupを使いましょう。
#その他
サンプルで書いた unique() なんかは<Formik />
中でで利用していると、検証の対象外の入力フォームを操作していても動作しているみたいです。このあたり情報をお持ちでしたら誰か教えて下さい。