DEV Community

Cover image for How To Use Formik & Yup For Form Validations
Deborah Kurz
Deborah Kurz

Posted on

How To Use Formik & Yup For Form Validations

Welcome back, fellow coders!

Today we are going to be using the frontend library known as ‘Formik’ combined with a schema builder called “Yup” in a step-by-step framework to help you understand and implement validations on your React forms.

What are Formik and Yup?

When I first started learning Formik (and using Yup with it) I didn’t feel confident in it because I didn't understand what it was for. So, before we begin with the step-by-step process, let’s make sure we’re on the same page when it comes to understanding what both Formik and Yup are and why they are important.
Formik is a library used in React, and its official docs proudly state that it allows you to “Build forms in React, without the tears” (see ‘*Formik’ in the Reference section). What that statement really means is that Formik keeps track of values, validations, submissions, etc. in order to save you time and allow you to mentally keep track of more important details in your code (*Formik).
As I mentioned previously, Yup is a schema builder (and also a library) that allows you to define a schema and use it hand-in-hand with Formik to create validations (*Yup).

Okay, now let’s talk about the steps we can use in React to validate a form with Formik and Yup.

Formik and Yup Basics

Before we dive into a hands-on example, let’s detail out the steps we will need to take:

  1. Import the necessary libraries to get Formik and Yup running.
  2. Create a function for our Yup schema.
  3. Inside the Formik function, define initial values, validation schema, and instructions for onSubmit.
  4. Update our JSX to use Formik.

Let’s get started!

Formik and Yup Step-By-Step Guide

Recently I built a simple goals-tracker application and used Formik in the “Add Goal” form to validate the user intake and ensure that the value was a string between 1-20 characters long.
I’ll be using the “Add Goal” form as an example going forward.
To start with, this is what the form looked like in the User Interface:

Add goal button

Now that you know what the basic UI looks like, let’s transition to the code.
This is where we will start (without any Formik or Yup):

import React from "react";

function AddGoal({ handleGoal }){ 

    return(
        <div>
            <form onSubmit= >
                <input 
                    id="goal"
                    name="goal"
                    type="text" 
                    value=
                    placeholder = "Add A New Goal"
                    onChange=
                />
                <br></br>
                <button type="submit">Add My Goal</button>
                <br></br>
                <p></p>
                <br></br>
            </form>
        </div>
    )
};

export default AddGoal
Enter fullscreen mode Exit fullscreen mode

Now let’s implement the steps we outlined above:

1. Import the necessary libraries to get Formik and Yup running.

Near the top of our page we will import the needed libraries:

import React from "react";
import { useFormik } from "formik";
import * as yup from "yup";

// Rest of code

Enter fullscreen mode Exit fullscreen mode

2. Create a function for your Yup schema.

Now that Formik and Yup are available to us, we’re going to use Yup first to create our validations ("Add Goal" only has one user input, “goal”, but if you have more, you need to put a comma between them):

function AddGoal({ handleGoal }){
    const formschema = yup.object().shape({
        goal: yup.string().required("Please enter a goal with at least 1 character.").max(20)
    })

// Rest of code

Enter fullscreen mode Exit fullscreen mode

In the code above we are declaring a variable “formschema” and using yup with its ‘object()’ and ‘shape()’ methods. These methods are basically saying “This is an object and its ‘shape’ will look like the following”.
On our "goal" key, which we will use in a POST request to a database later on, we are once again using Yup with the following methods to create validations for our user input: .string(), .required(), and .max().

Although our code technically isn’t working yet, let’s pretend it is for a moment and get a visual of what happens when we try to add a goal without entering anything into our input form:

Finished form with validation error example
Here we can see that the validation has triggered the ".required()" part of our formschema and thrown an error.

Okay, back to reality where we have NOT yet done everything needed yet to get these validation errors looking like the above photo… Let’s move on to the next step.

3. Inside the Formik function, we will define initial values, validation schema, and instructions for when onSubmit is triggered.

Next on our to-do list is to create a variable called ‘formik'. Inside this variable, we will call the ‘useFormik’ hook and define the initial value(s) for our form, call our formschema to define the schema inside the useFormik hook, make a post request with our new user value, and finally reset the form.

Let’s break this process up into pieces:
1) First, declare a variable and assign the useFormik hook to it:

function AddGoal({ handleGoal }){
    const formschema = yup.object().shape({
        goal: yup.string().required("Please enter a goal with at least 1 character.").max(20)
    })

    const formik = useFormik({})

    //Rest of code

Enter fullscreen mode Exit fullscreen mode

2) Define initial values for the form:

function AddGoal({ handleGoal }){
    const formschema = yup.object().shape({
        goal: yup.string().required("Please enter a goal with at least 1 character.").max(20)
    })

    const formik = useFormik({
        initialValues: {
            goal: ""
        }, 
    })

    //Rest of code

Enter fullscreen mode Exit fullscreen mode

(Make sure to include a comma at the end of your initialValues object).

3) Use formschema when adding the validationSchema key:

function AddGoal({ handleGoal }){
    const formschema = yup.object().shape({
        goal: yup.string().required("Please enter a goal with at least 1 character.").max(20)
    })

    const formik = useFormik({
        initialValues: {
            goal: ""
        },
        validationSchema: formschema,
    })

    // Rest of code

Enter fullscreen mode Exit fullscreen mode

4) Give onSubmit a function with the “values” and “{ resetForm }” arguments:

function AddGoal({ handleGoal }){
    const formschema = yup.object().shape({
        goal: yup.string().required("Please enter a goal with at least 1 character.").max(20)
    })

    const formik = useFormik({
        initialValues: {
            goal: ""
        },
        validationSchema: formschema,
        onSubmit: (values, { resetForm })=>{}
    })

    // Rest of code

Enter fullscreen mode Exit fullscreen mode

Inside onSubmit we will create our POST request (which we will not be going into detail on how to build in this article). However, in our second ".then()", we will call “resetForm(‘’)” in order to clear the form once a user has submitted it.

function AddGoal({ handleGoal }){
    const formschema = yup.object().shape({
        goal: yup.string().required("Please enter a goal with at least 1 character.").max(20)
    })

    const formik = useFormik({
        initialValues: {
            goal: ""
        },
        validationSchema: formschema,
        onSubmit: (values, { resetForm })=>{

            const configObj = {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(values)
            }
            const url = `http://localhost:5555/goals`
            fetch(url, configObj)
            .then(r=>r.json())
            .then(goalObj => {
                handleGoal(goalObj);
                resetForm("");
            })
        }
    })

//Rest of code

Enter fullscreen mode Exit fullscreen mode

And there you have it! We have finished creating our formik function! That just leaves us one last thing to do:

4. Update the JSX to use Formik
(Our JSX before updating:)

// Previous code

return(
        <div>
            <form onSubmit= >
                <input 
                    id="goal"
                    name="goal"
                    type="text" 
                    value=
                    placeholder = "Add A New Goal"
                    onChange=
                />
                <br></br>
                <button type="submit">Add My Goal</button>
                <br></br>
                <p></p>
                <br></br>
            </form>
        </div>
    )
};

export default AddGoal

Enter fullscreen mode Exit fullscreen mode
  • Let’s update the following items in our JSX: Update "onSubmit" with Formik:
// Previous code

return(
        <div>
          <form onSubmit={formik.handleSubmit}>

          // Rest of code

Enter fullscreen mode Exit fullscreen mode
  • (Inside our input tag) update "value" with Formik:
// Previous code

return(
        <div>
          <form onSubmit={formik.handleSubmit}>
                <input 
                    id="goal"
                    name="goal"
                    type="text" 
                    value={formik.values.goal}
                    placeholder = "Add A New Goal"
                    onChange=
                />

          // Rest of code

Enter fullscreen mode Exit fullscreen mode
  • (Still inside our input tag) update "onChange" with Formik:
// Previous code

return(
        <div>
          <form onSubmit={formik.handleSubmit}>
                <input 
                    id="goal"
                    name="goal"
                    type="text" 
                    value={formik.values.goal}
                    placeholder = "Add A New Goal"
                    onChange={formik.handleChange}
                />

          // Rest of code

Enter fullscreen mode Exit fullscreen mode
  • Let’s circle back to when we demonstrated the validation errors earlier in this article and finish setting that up by creating styled errors in a

    tag:

// Previous code

    return(
        <div>
            <form onSubmit={formik.handleSubmit}>
                <input 
                    id="goal"
                    name="goal"
                    type="text" 
                    value={formik.values.goal}
                    placeholder = "Add A New Goal"
                    onChange={formik.handleChange}
                />
                <br></br>
                <button type="submit">Add My Goal</button>
                <br></br>
                <p style={{ color: "red" }}>{formik.errors.goal}</p>
                <br></br>
            </form>
        </div>
    )
};

export default AddGoal

Enter fullscreen mode Exit fullscreen mode

And that’s it! We've just walked through how to easily create Formik/Yup validations in code!

Recap:

In case you ever need a quick reference of Formik and Yup in the future, here are the steps you need to follow to get your forms validating properly:

1. Import the necessary libraries to get Formik and Yup running.

2. Create a function for your Yup schema.

3. Create a function that calls the useFormik hook. Inside the hook, define:
1) initialValues.
2) validationSchema
3) onSubmit [hand it a function with ‘values’ and { resetForm }. Make your POST request and call resetForm(“”) to clear input].

4. Update your JSX to use Formik:
1) In your form tag, add formik.handleSubmit to ‘onSubmit’.
2) In your input tag, add formik.values.(goal) to ‘value’.
3) In your input tag, add formik.handleChange to ‘onChange’.
4) Create a paragraph tag with styling for formik.errors.(goal).

Happy Coding!

Reference

*Formik: https://formik.org/

*Yup: https://www.npmjs.com/package/yup

Flatiron School's Phase-4 Formik and Form Validation Lesson was also used for reference by the author, though not quoted. For more information on Flatiron's School, please visit their website.

Top comments (0)