React
reactnative
Formik

Formik(というかYup)でemailがユニークかどうかとかpasswordが一致するかなどを検証する


前提

ReactNativeでの話です。あと、この記事の続き的なものです。Formikの基本的な動作はそちらを御覧ください。


やりたいこと


  • emailが既に登録されていないか検証

  • passwordとpasswordConfirm(確認用)が一致するかどうか検証

下記のような感じ。

スクリーンショット 2018-11-25 7.06.25.png


やりかた


emailが既に存在するかどうか

.test()を利用してみます。.test()はカスタムバリデーションの実装に利用できる関数で、

.test([テスト名],[エラーメッセージ],[関数])

という形式で、引数で与えられたvalueを検証し、true, falseを返すことでカスタムバリデーションを実装できるようです。


passwordが一致するかどうか

Yupでは、

.oneOf()

という形式で他の値を参照できるので利用してみます。


実装


App.js

import React from 'react';

import { StyleSheet, Text, View } from 'react-native';
import { Formik, yupToFormErrors } from 'formik';
import { Card, Button, FormLabel, FormInput, FormValidationMessage } from 'react-native-elements';
import * as Yup from 'yup';

export default class App extends React.Component {
render() {
return (
<View style={{ paddingVertical: 60 }}>
<Formik
initialValues={{
name: '',
email: '',
password: '',
passwordConfirm: ''
}}
onSubmit={values => this._handleSubmit(values)}
validationSchema={Yup.object().shape({
name: Yup
.string()
.required('名前は必須です。'),
email: Yup
.string()
.email('形式がemailではありません。')
.required('emailは必須です。')
+ .test('email-test', '既に存在します。', (value) => {
+ if (value === 'test@test.com') {
+ return false;
+ } else {
+ return true;
+ }
+ }),
password: Yup
.string()
.min(4, 'パスワードは最低4文字です。')
.required('passwordは必須です。'),
passwordConfirm: Yup
.string()
+ .oneOf([Yup.ref('password')], 'passwordが一致しません。')
.required('passwordは必須です。'),
})}
>
{
({ handleChange, handleSubmit, values, errors }) => (
<Card title='登録フォーム'>
<FormLabel>Name</FormLabel>
<FormInput
autoCapitalize='none'
onChangeText={handleChange('name')}
value={values.name}
/>
<FormValidationMessage>{errors.name}</FormValidationMessage>

<FormLabel>Email</FormLabel>
<FormInput
autoCapitalize='none'
onChangeText={handleChange('email')}
value={values.email}
/>
<FormValidationMessage>{errors.email}</FormValidationMessage>

<FormLabel>Password</FormLabel>
<FormInput
autoCapitalize='none'
onChangeText={handleChange('password')}
value={values.password}
secureTextEntry
/>
<FormValidationMessage>{errors.password}</FormValidationMessage>

<FormLabel>PasswordConfirm</FormLabel>
<FormInput
autoCapitalize='none'
onChangeText={handleChange('passwordConfirm')}
value={values.passwordConfirm}
secureTextEntry
/>
<FormValidationMessage>{errors.passwordConfirm}</FormValidationMessage>

<Button
title="登録"
onPress={handleSubmit}
buttonStyle={{ marginTop: 20 }}
/>
</Card>
)
}
</Formik>
</View>
);
}

_handleSubmit = (values) => {
alert(JSON.stringify(values));
}
}


上記では、emailは単にtest@test.comに一致するかどうかで検証していますが、実際にはaxios等でAPIを照会することになります。