TutorialsCourses
Course Menu
Formik for Beginners

Basic Errors

Introduction

Errors are a necessary part of all forms. Form requirements can range from very simple, to very complex. They range from simpler synchronous validations, to also including asynchronous validation. Formik has first class support for both synchronous and asynchronous validation. The basic form of this is the validate function. It can be a sync or async function.

Checking for Errors

The way that Formik handles errors is that the returned error structure should map an error message to same structure as your values. In our case we have a single level object with a firstName key. So if our value below is set like this, then our error should map accordingly.

{
  firstName: ''
}

{
  firstName: 'Erorr message',
}

It doesn't matter how you check for errors in this function it just matters that the structure is returned, or if valid that an empty object is returned.

So here we check if firstName is empty and if it is we set an error message.

<Formik
  initialValues={{
    firstName: "",
  }}
  onSubmit={handleSubmit}
  validate={(values) => {
    let errors = {};
    if (!values.firstName) {
      errors.firstName = "Required";
    }
    return errors;
  }}
></Formik>

Controlling Error Rendering

Here we will control how an error gets rendered. The useField hook and Field both supply a meta object. The meta object is meta information about the specific field that's being rendered.

So in our case it's referencing meta information about our firstName field. A field might be in an erroneous state but we don't want to bombard the user with the error message before they've even touched the field.

When a user interacts with a field, then triggers an onBlur the touched value is set to true. This allows us to now display an error message once we know it's been touched and also that an error exists.

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

Formik Helper ErrorMessage

Generally the standard for displaying an error is that you need to have touched the field, and that an error exists. Formik ships with the ErrorMessage helper component.

import { ErrorMessage } from "formik";

You supply it with a name. When that fields contains an error and the field has been touched. Then it will display whatever the error text is. You can supply any component you'd like and it will pass the error text as a child.

<div>
  <Field name="firstName" className="border-2" />
  <ErrorMessage name="firstName" component="div" />
</div>

Submission

One thing to realize is that if the user submits all fields are set to the touched status. So even if the user didn't trigger an onBlur on the firstName field. Then opted to click the Submit button, the error messages will pop up.

This is generally what you want but if this isn't than you may need to handle how errors are displayed in your form and not use the ErrorMessage component.

Putting it all Together

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

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}
        validate={(values) => {
          let errors = {};
          if (!values.firstName) {
            errors.firstName = "Required";
          }
          return errors;
        }}
      >
        {() => {
          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;