0
votes

I am working on a form that is made with Formik, Yup, and ReactJS. In the date field, I am trying to validate if the user is 18 years old. I have passed the following as validationSchema paremeter in Formik:

import differenceInYears from "date-fns/differenceInYears";
...
...
...
    dob: Yup.date()
              .nullable()
              .test("dob", "Should be greater than 18", function (value) {
                return differenceInYears(value, new Date()) >= 18;
              }),

The name of the formik input field is dob. But it shows the validation error even if I enter a valid date which is 18 years old. So, how to validate it properly?

2

2 Answers

2
votes

You need to swap the date params:

differenceInYears(new Date(), new Date(value)) >= 18;

If you check date-fns docs, the first argument should be the later date.

Also you need to parse the field value into a Date.

-1
votes

My solution:


import React from "react";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";
import s from "./Registration.module.css";

const SignupSchema = Yup.object().shape({
  firstName: Yup.string().required("Required"),
  lastName: Yup.string().required("Required"),
  birthdate: Yup.date()
    .max(new Date(Date.now() - 567648000000), "You must be at least 18 years")
    .required("Required"),
  password: Yup.string()
    .min(4, "Too Short!")
    .max(50, "Too Long!")
    .required("Required"),
  email: Yup.string().email("Invalid email").required("Required"),
});

export const RegistrationForm = () => (
  <div className={s.mainLoginForm}>
    <h1>Sign up</h1>
    <Formik
      initialValues={{
        firstName: "",
        lastName: "",
        email: "",
        password: "",
        birthdate: "",
      }}
      validationSchema={SignupSchema}
      onSubmit={(values) => {
        // same shape as initial values
        console.log(values);
      }}
    >
      {({ errors, touched }) => (
        <Form>
          <div className={s.inputsFlex}>
            <Field
              className={s.regInput}
              placeholder="email"
              name="email"
              type="email"
            />
            {errors.email && touched.email ? (
              <div className={s.formControl}>{errors.email}</div>
            ) : null}
            <Field
              className={s.regInput}
              placeholder="password"
              name="password"
              type="password"
            />
            {errors.password && touched.password ? (
              <div className={s.formControl}>{errors.password}</div>
            ) : null}
            <Field
              className={s.regInput}
              placeholder="firstName"
              name="firstName"
            />
            {errors.firstName && touched.firstName ? (
              <div className={s.formControl}>{errors.firstName}</div>
            ) : null}
            <Field
              className={s.regInput}
              placeholder="lastName"
              name="lastName"
            />
            {errors.lastName && touched.lastName ? (
              <div className={s.formControl}>{errors.lastName}</div>
            ) : null}
            <Field className={s.regInput} name="birthdate" type="date" />
            {errors.birthdate && touched.birthdate ? (
              <div className={s.formControl}>{errors.birthdate}</div>
            ) : null}
            <button className={s.regBtn} type="submit">
              Sign up
            </button>
          </div>
        </Form>
      )}
    </Formik>
  </div>
);


You can add 4 days for leap (intercalary) year 86 400 000 * 4 = 345 600 000