DEV Community

Tiamiyu Sikiru Abidemi
Tiamiyu Sikiru Abidemi

Posted on

Form and Form Validation in React using Formik and Yup

As a frontend and software engineer in general, security is one of the key concerns when building web applications, second only to performance. So taking time to prevent external form abuse by malicious users is never a wasted effort.
We'll be working through form valiadation and form in React by building a contact form, using Yup and Formik.

Prerequisites

Before you begin this tutorial you'll need the following:

- React knowledge

  • Yup Installed
  • Formik Installed

Installing React

setting up our project

 npx create-react-app yup-formik-validation
 cd yup-formik-validation
 yarn start
Enter fullscreen mode Exit fullscreen mode

Formik

Formik is a library that manages form values(datas),validation and error messages, and handling of form submission. Making interacting with form as easy as a walk in the park.

Installing Formik

yarn add formik 
Enter fullscreen mode Exit fullscreen mode

Yup

Yup is a JavaScript schema builder for value parsing and validations.

Installing Yup

 yarn add yup 
Enter fullscreen mode Exit fullscreen mode

Initialize Module

After all installation we'll be working inside our App.js file.

> app.js
import React, { useState } from 'react';
import { Formik, Field } from 'formik';
import * as Yup from 'yup';
Enter fullscreen mode Exit fullscreen mode

Our next line of action is setting up our Form and form fields using Formik, we'll be working on 4 fields namely:

  • First Name Field
  • Last Name Field
  • Email Field
  • Message Field (using textarea element)

Before we move forward lets talk about formik element and some of it attributes.
Formik element housing both Form element and it child element (Field elements).

  <Formik>
    <Form>
      <Field></Field>
   </Form>
    ...
  </Formik>
Enter fullscreen mode Exit fullscreen mode

Formik element also have some attributes that are required when setting up a form. Listed below:

  • InitialValues : it's contains the initial values of our fields element.
initialValues={{
   firstName: '',
   lastName: '',
   email: '',
   message: ''
}}
Enter fullscreen mode Exit fullscreen mode
  • ValidationSchema : houses our Yup validation schema, which we'll be talking about below.
> // declared outside of our App function.
const validationSampleSchema = Yup.object().shape({
   firstName: Yup.string().min(1, 'First Name is too 
      short!').required('First Name field is required'),
   lastName: Yup.string().min(1, 'Last Name is too 
      short!').required('Last Name field is required'),
   email: Yup.string().email('Invalid email').required('Email 
      field is required'),
   message: Yup.string().required('Message field is required')
})
Enter fullscreen mode Exit fullscreen mode

Yup has different data type methods validation and conditions methods e.g min() and required()

validationSchema={customValidationSchema}
Enter fullscreen mode Exit fullscreen mode

passing of our custom schema to the validationSchema attribute

  • onSubmit : submission function, which is an eventListener.
onSubmit={(values, { setSubmitting, resetForm }) => {
  // when the handleSubmit is triggered on our submit button 
     below, every expressions and method actions get triggered

  // Reseting our form fields to empty
     resetForm({ values: "" });
}}
Enter fullscreen mode Exit fullscreen mode

Rendering our Form and making Formik props and methods available

{(
  {
    setFieldValue,
    values,
    errors,
    touched,
    handleSubmit
  }) => (
     <>
       <form></form>
     <>
)}
Enter fullscreen mode Exit fullscreen mode
<form>
   <div className='row'>
      <div className='col-md-6'>
         <div className="form-group mb-3">
            <label>First Name</label>
            <Field className="form-control" name="firstName" 
              value={values.firstName} placeholder="First 
              Name"/>
            {errors.firstName && touched.firstName && (<small 
            className="text-danger">{errors.firstName} 
            </small>)}
        </div>
      </div>
      <div className='col-md-6'>
         <div className="form-group mb-3">
            <label>Last Name</label>
            <Field name="lastName" className="form-control" 
             value={values.lastName} placeholder="Last Name" 
            />
            {errors.lastName && touched.lastName && (<small 
             className="text-danger">{errors.lastName} 
             </small>)}
         </div>
      </div>
      <div className='col-md-12'>
         <div className="form-group mb-3">
            <label>Email</label>
            <Field type="email" className="form-control" 
              value={values.email} name="email" 
              placeholder="Email" />
            {errors.email && touched.email && (<small 
             className="text-danger">{errors.email}</small>)}
          </div>
       </div>
       <div className="col-md-12">
          <div className="form-group mb-3">
            <label>Drop Message</label>
            <Field name="message">
                  {({
                      field,
                      meta,
                  }) => (
                 <div>
                   <textarea className="form-control" 
                    name="message" id="message"
                    placeholder="Type here" value= 
                    {values.message} rows="3" {...field} > 
                  </textarea>
                  {meta.touched && meta.error && ( <small 
                  className="text-danger">{meta.error}
                  </small>)}
                </div>
                )}
            </Field>
         </div>
       </div>
    </div>
    <button type="submit" className='btn btn-sm btn-success' 
     onClick={handleSubmit}>Submit</button>
 </form>
Enter fullscreen mode Exit fullscreen mode

two Field attributes are important to us, in our above code:

  • name: automatically hook up inputs to Formik using the name attribute to match up with Formik state. <Field name={'email'}/> name attribute matches the property declared in our initialValues.
  • value: Formik access the value through the value attribute value={values.fieldName} e.g value={values.email}

Yup Formik Validation Contact Form

Errors

{errors.firstName && touched.firstName && (<small className="text-danger">{errors.firstName}</small>)}
Enter fullscreen mode Exit fullscreen mode

whenever our field has been touched, and it contains an error, display it.
The error setup above works with our firstName field.

Submit

<button type="submit" className='btn btn-sm btn-success' 
  onClick={handleSubmit}>Submit</button>
Enter fullscreen mode Exit fullscreen mode

onClick eventlistener triggers our handleSubmit (Formik method), which is available to us when we rendered our form.

Updated onSubmit Formik attribute

onSubmit={(values, { setSubmitting, resetForm }) => {

  // assigning our values from the fields to payload variable.   
  const payload = values;

  // we have a handleNext function that saves our contact form 
     field values into a result state.
  handleNext(payload);

  // Reseting our form fields to empty
  resetForm({ values: "" });
}}
Enter fullscreen mode Exit fullscreen mode
const [showResult, setShowResult] = useState(false);
const [result, setResult] = useState({});

const handleNext = (payload) => {
    setResult(payload)
    setShowResult(true);
}
Enter fullscreen mode Exit fullscreen mode

Yup Formik Validation Contact From End Result

Demo
Yup Formik Validation Contact Form Demo

Conclusion

Working with form in react is very tasking, coupled with trying to setup validation to our form fields, as we all know Form Validation is an integral part of building a web application, and Formik helps in working with forms in React doing the hard part and leaving us to worry more on other important part in our web app development, same way Yup handles our validations.

Check out the following official documentations to get a broader explanations on our subject matter:

You can also find the full code source on github:

Attributions

Have questions? Facing issues implementing?

Drop a comment let work through them together.

Do you find this helpful?

You can follow me here on Dev and also on Twitter:

Top comments (0)