Reactでのフォーム管理:FormikとYupを使用したバリデーション

Reactでのフォーム管理:FormikとYupを使用したバリデーション

Reactでフォームを管理する際、FormikとYupを組み合わせて効率的にバリデーションを実装する方法について解説します。このセットアップにより、複雑なフォームでも簡潔にバリデーションを追加でき、ユーザーエクスペリエンスを向上させることができます。

1. Reactプロジェクトのセットアップ

まず、新しいReactプロジェクトを作成し、必要なライブラリをインストールします。

npx create-react-app formik-validation
cd formik-validation
npm install formik yup

2. Formikの基本設定

Formikを使って、フォームの状態を管理します。フォームの値やエラーメッセージ、送信処理を簡単に取り扱えるようになります。

// src/FormComponent.js
import React from 'react';
import { Formik, Field, Form } from 'formik';

function FormComponent() {
  return (
    <Formik
      initialValues={{ name: '', email: '' }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="name" type="text" />
        <Field name="email" type="email" />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  );
}

export default FormComponent;

3. Yupでバリデーションスキーマの作成

Yupを使用して、フォームフィールドに対するバリデーションルールを定義します。

import * as Yup from 'yup';

const validationSchema = Yup.object({
  name: Yup.string().required('名前は必須です'),
  email: Yup.string().email('有効なメールアドレスを入力してください').required('メールアドレスは必須です'),
});

4. FormikとYupを統合する

FormikにYupバリデーションスキーマを統合して、フォームの各フィールドをバリデートします。

// src/FormComponent.js
import { Formik, Field, Form, ErrorMessage } from 'formik';
import * as Yup from 'yup';

const validationSchema = Yup.object({
  name: Yup.string().required('名前は必須です'),
  email: Yup.string().email('有効なメールアドレスを入力してください').required('メールアドレスは必須です'),
});

function FormComponent() {
  return (
    <Formik
      initialValues={{ name: '', email: '' }}
      validationSchema={validationSchema}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <div>
          <Field name="name" type="text" />
          <ErrorMessage name="name" component="div" />
        </div>
        <div>
          <Field name="email" type="email" />
          <ErrorMessage name="email" component="div" />
        </div>
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  );
}

export default FormComponent;

5. バリデーションエラーメッセージの表示

エラーメッセージをフォームフィールドの下に表示するために、`ErrorMessage`コンポーネントを使います。

<ErrorMessage name="name" component="div" className="error" />
<ErrorMessage name="email" component="div" className="error" />

6. 初期値の設定

フォームの初期値を設定して、フォームが初期化されたときに表示されるデータを制御します。

<Formik
  initialValues={{ name: 'John Doe', email: 'johndoe@example.com' }}
  validationSchema={validationSchema}
  onSubmit={(values) => console.log(values)}
>
  ...
</Formik>

7. バリデーションのタイミング

Formikでは、フォームが変更されるたびにバリデーションを行うことができます。バリデーションのタイミングを制御する方法について説明します。

<Formik
  validationSchema={validationSchema}
  validateOnChange={true} // 入力時にバリデーション
  validateOnBlur={false}  // フォーカスアウト時にバリデーション
>
  ...
</Formik>

8. フォームの送信時の処理

フォームの送信時に実行される処理を`onSubmit`で指定します。成功した場合、失敗した場合に適切な処理を行います。

onSubmit={(values, { setSubmitting }) => {
  setTimeout(() => {
    console.log(values);
    setSubmitting(false);
  }, 400);
}}

9. 条件付きバリデーション

Yupでは条件付きバリデーションを設定できます。例えば、特定のフィールドがある条件を満たした場合のみ、他のフィールドのバリデーションを行うことができます。

const validationSchema = Yup.object({
  name: Yup.string().required('名前は必須です'),
  email: Yup.string().email('有効なメールアドレスを入力してください').required('メールアドレスは必須です'),
  age: Yup.number().when('name', {
    is: 'John',
    then: Yup.number().required('年齢は必須です'),
  }),
});

10. フォームの状態管理

Formikのvaluesオブジェクトを使って、フォーム内の全ての値にアクセスできます。これを利用して動的にフォームの状態を管理する方法について解説します。

<Formik
  initialValues={{ name: '', email: '' }}
  onSubmit={values => console.log(values)}
>
  {({ values }) => (
    <div>
      <input name="name" value={values.name} />
      <input name="email" value={values.email} />
    </div>
  )}
</Formik>

11. フォームのリセット

Formikを使うことで、フォームの状態をリセットするのが簡単です。resetFormを使って、フォームの入力内容を初期状態に戻します。

<Formik
  initialValues={{ name: '', email: '' }}
  onSubmit={(values, { resetForm }) => {
    console.log(values);
    resetForm();
  }}
>
  ...
</Formik>

12. 複雑なフォームの管理

Formikを使うことで、複雑なフォーム(例えば複数の入力フィールドや動的なフォーム)を簡単に管理できます。FieldArrayを使って、動的なフィールドを追加する方法を解説します。

import { FieldArray } from 'formik';

<Formik
  initialValues={{ friends: [''] }}
  onSubmit={(values) => console.log(values)}
>
  {({ values }) => (
    <Form>
      <FieldArray
        name="friends"
        render={arrayHelpers => (
          <div>
            {values.friends.map((friend, index) => (
              <div key={index}>
                <Field name={`friends.${index}`} />
                <button
                  type="button"
                  onClick={() => arrayHelpers.remove(index)}
                >
                  Remove
                </button>
                <button
                  type="button"
                  onClick={() => arrayHelpers.push('')}
                >
                  Add Friend
                </button>
              </div>
            ))}
          </div>
        )}
      />
      <button type="submit">Submit</button>
    </Form>
  )}
</Formik>