😸

Formikを使ったYupバリデーションで、最大文字数を可変させたい!

2023/09/05に公開

はじめに

氏名とメモなどの長い入力になりそうなものを編集するための共通モーダルみたいなもので、編集対象のものによって最大値のバリデーション値を変えたいことってありますよね?(氏名は10文字まででメモは100文字までなど)
今回はそんな時どうやって長さを変化させればいいのかを調べました。

結論

いきなり結論です。
方法としてはとても単純で、FormikのvalidationSchemaにYup.objectを返す関数を渡してあげてその関数の引数で最大値をもらう形で可変にできます。

FormikのvalidationSchemaの型を見に行くと下記のようになっています。
そのため関数で渡しても問題ないということになります!

/**
  * A Yup Schema or a function that returns a Yup schema
  */
validationSchema?: any | (() => any);

実装例

validationSchema.ts
import * as Yup from "yup";

export const validationSchema = ({ maxLength }: { maxLength: number }) =>
  Yup.object({
    value: Yup.string().max(maxLength, `文字の最大値は${maxLength}です。`),
  });
Form.tsx
import React from 'react';
import { Formik } from 'formik';
import { validationSchema } from './validation';

export const SignupForm: React.FC = () => {
  return (
    <Formik
      initialValues={{ value: '' }}
      validationSchema={() => validationSchema({maxLength: 16})} // 編集対象のものによって長さを変える
      onSubmit={(values, { setSubmitting }) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          setSubmitting(false);
        }, 400);
      }}
    >
      {formik => (
        <form onSubmit={formik.handleSubmit}>
          <label htmlFor="value">value</label>
          <input
            id="value"
            type="text"
            {...formik.getFieldProps('value')}
          />
          {formik.touched.value && formik.errors.value ? (
            <div>{formik.errors.value}</div>
          ) : null}

          <button type="submit">Submit</button>
        </form>
      )}
    </Formik>
  );
};

終わりに

これでvalidationSchemaを使いまわすことができるため、同じようなパターンで長さだけ変わっているYup.Objectを沢山複製しなくてもすみますね!

Discussion