TutorialsCourses
Course Menu
Formik for Beginners

Easy Error Handling and Data Validation with Yup

Introduction

Formik has first class support for yup. It's a declarative way to handle both synchronous and asynchronous error handling. It has methods that allow you to transform, and do custom error checking when necessary.

Declarative Errors

To use yup you can import it piece by piece. Our Formik values are in the shape of an object. So we import the object validation from yup. Also we will be validating just strings so we'll import the string validator as well.

To put it together we first declare we want to check a shape.

object().shape({});

Then it excepts that we describe the shape of our data using the keys that map to the keys on our values. In our case we want to check our firstName isn't empty.

Inside of our shape we give it our object, and specify that firstName is a string() and that it is required(). The value you pass to the required() call will be the message when this validation fails. In our case the message is Required.

{
  firstName: string().required("Required"),
}
import { object, string } from "yup";

const NameValidation = object().shape({
  firstName: string().required("Required"),
});

Using with Formik

Formik has first class support, so rather than calling validate function we provide a validationSchema. Formik internals know that it's a yup schema. It doesn't matter if you have sync or async validations in Yup it'll still work.

Formik knows how to map the errors returned from yup to the appropriate structure for it's own internal error system.

<Formik
  initialValues={{
    firstName: "",
  }}
  onSubmit={handleSubmit}
  validationSchema={NameValidation}
/>

Putting it All Together

import React from "react";
import { Formik, Form, Field, useField, ErrorMessage } from "formik";
import { object, string } from "yup";

const NameValidation = object().shape({
  firstName: string().required("Required"),
});

const MySpecialField = () => {
  const [field, meta] = useField("firstName");
  return (
    <div>
      <input {...field} className="border-2" />
      {meta.touched && meta.error && <div>{meta.error}</div>}
    </div>
  );
};

function App() {
  const handleSubmit = (values) => {
    console.log(values);
  };

  return (
    <div className="App">
      <Formik
        initialValues={{
          firstName: "",
        }}
        onSubmit={handleSubmit}
        validationSchema={NameValidation}
      >
        {() => {
          return (
            <Form className="h-screen flex content-center flex-col justify-center">
              <div className="space-x-4 flex content-center justify-center">
                <div>
                  <Field name="firstName" className="border-2" />
                  <ErrorMessage name="firstName" component="div" />
                </div>
                <MySpecialField />
                <button
                  type="submit"
                  className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
                >
                  Submit
                </button>
              </div>
            </Form>
          );
        }}
      </Formik>
    </div>
  );
}

export default App;