Formik は、複雑な検証を伴うフォームを容易に管理できるように設計されています。Formik は、同期および非同期のフォームレベルとフィールドレベルの検証をサポートしています。さらに、Yup を介したスキーマベースのフォームレベル検証のサポートが組み込まれています。このガイドでは、上記のすべてについて詳細に説明します。
フォームレベルの検証は、関数が実行されるたびにフォームのすべての `値` とプロパティに完全にアクセスできるため、依存フィールドを同時に検証できるため便利です。
Formik でフォームレベルの検証を行うには、2 つの方法があります
`<Formik>` と `withFormik()` は、同期または非同期関数を引数として受け取る `validate` という prop/オプションを受け取ります。
// Synchronous validationconst validate = (values, props /* only available when using withFormik */) => {const errors = {};if (!values.email) {errors.email = 'Required';} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {errors.email = 'Invalid email address';}//...return errors;};// Async Validationconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms));const validate = (values, props /* only available when using withFormik */) => {return sleep(2000).then(() => {const errors = {};if (['admin', 'null', 'god'].includes(values.username)) {errors.username = 'Nice try';}// ...return errors;});};
`<Formik validate>` の詳細については、API リファレンスを参照してください。
上記のように、検証はあなた次第です。独自のバリデーターを作成するか、サードパーティのライブラリを使用してください。The Palmer Group では、オブジェクトスキーマの検証に Yup を使用しています。Joi や React PropTypes によく似た API を備えていますが、ブラウザで使用するのに十分小さく、ランタイムでの使用に十分高速です。私たちは Yup をとても気に入っているので、Formik には Yup オブジェクトスキーマ用の特別な設定オプション/プロパティである `validationSchema` があります。これは、Yup の検証エラーを、キーが `値` と `touched` に一致するきれいなオブジェクトに自動的に変換します。この対称性により、エラーメッセージに関するビジネスロジックを簡単に管理できます。
プロジェクトに Yup を追加するには、NPM からインストールします。
npm install yup --save
import React from 'react';import { Formik, Form, Field } from 'formik';import * as Yup from 'yup';const SignupSchema = Yup.object().shape({firstName: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('Required'),lastName: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('Required'),email: Yup.string().email('Invalid email').required('Required'),});export const ValidationSchemaExample = () => (<div><h1>Signup</h1><FormikinitialValues={{firstName: '',lastName: '',email: '',}}validationSchema={SignupSchema}onSubmit={values => {// same shape as initial valuesconsole.log(values);}}>{({ errors, touched }) => (<Form><Field name="firstName" />{errors.firstName && touched.firstName ? (<div>{errors.firstName}</div>) : null}<Field name="lastName" />{errors.lastName && touched.lastName ? (<div>{errors.lastName}</div>) : null}<Field name="email" type="email" />{errors.email && touched.email ? <div>{errors.email}</div> : null}<button type="submit">Submit</button></Form>)}</Formik></div>);
`<Formik validationSchema>` の詳細については、API リファレンスを参照してください。
Formik は、`<Field>`/`<FastField>` コンポーネントまたは `useField` フックの `validate` プロパティを介してフィールドレベルの検証をサポートしています。この関数は同期または非同期(Promise を返す)にすることができます。デフォルトでは、`onChange` と `onBlur` の後に実行されます。この動作は、トップレベルの `<Formik/>` コンポーネントでそれぞれ `validateOnChange` および `validateOnBlur` プロパティを使用して変更できます。変更/ぼかしに加えて、すべてのフィールドレベルの検証は送信試行の開始時に実行され、結果はトップレベルの検証結果と深くマージされます。
注:`<Field>/<FastField>` コンポーネントの `validate` 関数は、マウントされたフィールドでのみ実行されます。つまり、フォームのフロー中にフィールドのマウントが解除された場合(例:Material-UI の `<Tabs>` は、ユーザーがいた前の `<Tab>` のマウントを解除します)、これらのフィールドはフォームの検証/送信中に検証されません。
import React from 'react';import { Formik, Form, Field } from 'formik';function validateEmail(value) {let error;if (!value) {error = 'Required';} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)) {error = 'Invalid email address';}return error;}function validateUsername(value) {let error;if (value === 'admin') {error = 'Nice try!';}return error;}export const FieldLevelValidationExample = () => (<div><h1>Signup</h1><FormikinitialValues={{username: '',email: '',}}onSubmit={values => {// same shape as initial valuesconsole.log(values);}}>{({ errors, touched, isValidating }) => (<Form><Field name="email" validate={validateEmail} />{errors.email && touched.email && <div>{errors.email}</div>}<Field name="username" validate={validateUsername} />{errors.username && touched.username && <div>{errors.username}</div>}<button type="submit">Submit</button></Form>)}</Formik></div>);
Formik を使用して、それぞれ `validateForm` および `validateField` メソッドを使用して、フォームレベルとフィールドレベルの検証を手動でトリガーできます。
import React from 'react';import { Formik, Form, Field } from 'formik';function validateEmail(value) {let error;if (!value) {error = 'Required';} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)) {error = 'Invalid email address';}return error;}function validateUsername(value) {let error;if (value === 'admin') {error = 'Nice try!';}return error;}export const FieldLevelValidationExample = () => (<div><h1>Signup</h1><FormikinitialValues={{username: '',email: '',}}onSubmit={values => {// same shape as initial valuesconsole.log(values);}}>{({ errors, touched, validateField, validateForm }) => (<Form><Field name="email" validate={validateEmail} />{errors.email && touched.email && <div>{errors.email}</div>}<Field name="username" validate={validateUsername} />{errors.username && touched.username && <div>{errors.username}</div>}{/** Trigger field-level validationimperatively */}<button type="button" onClick={() => validateField('username')}>Check Username</button>{/** Trigger form-level validationimperatively */}<buttontype="button"onClick={() => validateForm().then(() => console.log('blah'))}>Validate All</button><button type="submit">Submit</button></Form>)}</Formik></div>);
ニーズに応じて `<Formik validateOnChange>` および/または `<Formik validateOnBlur>` プロパティの値を変更することにより、Formik が検証を実行するタイミングを制御できます。デフォルトでは、Formik は次のように検証メソッドを実行します
**「変更」イベント/メソッドの後**(`値` を更新するもの)
handleChange
setFieldValue
setValues
**「ぼかし」イベント/メソッドの後**(`touched` を更新するもの)
handleBlur
setTouched
setFieldTouched
送信が試行されるたびに
handleSubmit
submitForm
また、Formik のレンダー/注入されたプロパティを介して提供される命令型ヘルパーメソッドもあり、これらを使用して命令的に検証を呼び出すことができます。
validateForm
validateField
エラーメッセージは、フォームの検証に依存します。エラーが存在し、検証関数が値/初期値に一致する形状のエラーオブジェクト(そうあるべきです)を生成する場合、依存フィールドエラーは errors オブジェクトからアクセスできます。
import React from 'react';import { Formik, Form, Field } from 'formik';import * as Yup from 'yup';const DisplayingErrorMessagesSchema = Yup.object().shape({username: Yup.string().min(2, 'Too Short!').max(50, 'Too Long!').required('Required'),email: Yup.string().email('Invalid email').required('Required'),});export const DisplayingErrorMessagesExample = () => (<div><h1>Displaying Error Messages</h1><FormikinitialValues={{username: '',email: '',}}validationSchema={DisplayingErrorMessagesSchema}onSubmit={values => {// same shape as initial valuesconsole.log(values);}}>{({ errors, touched }) => (<Form><Field name="username" />{/* If this field has been touched, and it contains an error, display it*/}{touched.username && errors.username && <div>{errors.username}</div>}<Field name="email" />{/* If this field has been touched, and it contains an error, displayit */}{touched.email && errors.email && <div>{errors.email}</div>}<button type="submit">Submit</button></Form>)}</Formik></div>);
ErrorMessage コンポーネントを使用して、エラーメッセージを表示することもできます。
`isValidating` プロパティが `true` の場合
いいえ。代わりに `undefined` を使用してください。Formik は、空の状態を表すために `undefined` を使用します。`null` を使用すると、Formik の計算されたプロパティのいくつかの部分(たとえば、`isValid` など)は予期したとおりに機能しません。
Formik には Yup 検証の広範な単体テストがあるため、テストする必要はありません。ただし、独自の検証関数を作成している場合は、それらを単体テストする必要があります。Formik の実行をテストする必要がある場合は、それぞれ命令型の `validateForm` および `validateField` メソッドを使用する必要があります。
最新の Formik のニュース、記事、リソースが受信トレイに送信されます。