ReactにはReact Hook Formというフォームのバリデーションやらを実装できるライブラリが存在します。これにyupを合わせることでバリデーションの定義をより簡単に実装することができます。
やりたいこと
DBに存在する値の時もエラーを出したい。
実装
最初はこんなふうに実装していました。
const onSubmit: SubmitHandler<FormInput> = async (data) => {
const response = await GetAPI("http://localhost:8000/api/hoge", data)
if(response.status === 400){
//ここでエラー処理
}else{
//ここに正常処理
}
}
ここでいうGetAPIはユーザー名やパスワードからユーザーマスタを検索するfetchやaxiosだと考えてください。
最初はやり方がわからなくて,submitの中でAPIを送信してバックエンドでバリデーションを行ってました。その結果をフロント側でレスポンスのステータスで判断してメッセージを表示していたりしました。これだとバリデーションを行い、通ったはずなのにもう一度バリデーションを行うという流れになってしまい気持ち悪いです。
yup.test()
調べるとyup.test()を使うと動的なバリデーションが実装できるみたいでした。
const schema = yup.object().shape({
username:yup.string().required("必須入力です").test("バリデーション名", "バリデーションメッセージ", (input)=>{return true})
})
最終的にはこうなりました。
const schema = yup.object().shape({
username:yup.string().required("必須入力です").test("sameUsername", "既に使用されている名前です。", (input)=>{UsernameValidation(input)})
})
export async function UsernameValidation(username: string | undefined){
if (username === undefined){
return true
}
const response = await GetAPI("http://localhost:8000/api/hoge", username)
if (response.status === 200){
return false
} else {
return true
}
}
ユーザー名が存在しないときに返り値がtrueなのはこのバリデーションが重複の確認しか行わないためです。またレスポンスのステータスが200(正常終了)の時はユーザーが存在するためfalse。それ以外の時はユーザーが存在しないとみなしtrueを返しています。
まとめ
yupは非常に便利でこのような重複チェックやパスワードの再入力の一致なども簡単に実装できます。今回のだとレスポンスのステータスが200の時に失敗するという直感とは逆になってしまったが少し不満ですが、動きとしては今のところ問題ないのでとりあえずこれでやっています