Form validation using Yup and React Final Form

Form validation using Yup and React Final Form

What is React Final Form?

It's a library for managing form state and handling form submissions in React applications. It is designed to simplify the process of building and working with complex forms in React by providing a set of utilities and components to handle form validation, data synchronization, and user interactions.

What is Yup Validation?

Yup is a library for form validation. It is often used with React and React-based libraries to validate user input in forms, ensuring that the data submitted by users meets specific criteria.

Why should you use Yup and React Final Form together?

While you can use React Final Form to validate your user's inputs, yet Yup provides a declarative way to define validation rules for your form fields using schemas. This makes it easy to specify what data is valid and how it should be validated, enhancing code readability and maintainability. And since Yup and React Final Form are designed to work well together, that means you can seamlessly integrate Yup's validation schema into React Final Form, allowing you to define validation rules for your form fields and utilize Yup's extensive validation methods.

Adding React Final Form and Yup to your project:

First, you need to install both libraries. For Final Form and React Final Form:

npm install --save final-form react-final-form
//or
yarn add final-form react-final-form

For Yup:

npm install --save yup
//or
yarn add yup

Now you can start using both libraries.

Creating a simple form with both libraries:

In this example, I'm using a Next.js project. The code will be :

"use client"

import { Form, Field } from 'react-final-form'
import Styles from '../styles'

import { setIn } from "final-form";
import * as yup from "yup";

export default function Home() {

//---- Here is the Yup validation for the form components ----
    const validationSchema = yup.object({
        Age: yup.number().required("Must provide age"),
        Name: yup.string().required("Must provide name")
    });

    const validateFormValues = (schema) => async (values) => {
        if (typeof schema === "function") {
          schema = schema();
        }
        try {
          await schema.validateSync(values, { abortEarly: false });
        } catch (err) {
          const errors = err.inner.reduce((formError, innerError) => {
            return setIn(formError, innerError.path, innerError.message);
          }, {});

          return errors;
        }
    };

//---- Here is the React Final Form ----
    const validate = validateFormValues(validationSchema);

    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

    const onSubmit = async (values) => {
        await sleep(300);
        window.alert(JSON.stringify(values, 0, 2));
      };

  return (
    <>
    <Styles className=' bg-gray-600 text-black'>
    <main className="flex min-h-screen flex-col items-center justify-between p-24 ">
    <Form
    onSubmit={onSubmit}
    validate={validate}
    render={({ handleSubmit, form, submitting, pristine, values }) => (
        <form onSubmit={handleSubmit} className='bg-slate-400'>
        <Field name="Name">
          {({ input, meta }) => {
            return (
              <div>              
                <label>Name</label>
                <input {...input} placeholder="Name" />
                {meta.touched && meta.error && <span>{meta.error}</span>}
              </div>
            );
          }}
        </Field>
        <Field name="Age">
          {({ input, meta }) => (
            <div>
              <label>Age</label>
              <input {...input} placeholder="Age" />
              {meta.touched && meta.error && <span>{meta.error}</span>}
            </div>
          )}
        </Field>
        <div className="buttons">
          <button type="submit" disabled={submitting}>
            Submit
          </button>
          <button
            type="button"
            onClick={form.reset}
            disabled={submitting || pristine}
          >
            Reset
          </button>
        </div>
      </form>
    )} />
    </main>
    </Styles>    
    </>
  )
}

The outcome of the code will be:

And when you try to submit an empty form, the error will appear like this:

In the end, it's a simple example that doesn't show the variety and complexity of usage for both libraries, but it's enough to show how both libraries can be integrated with one another.

Conclusion

By combining React Final Form's form state management and form submission capabilities with Yup's flexible and schema-based validation, developers can create efficient and error-resistant forms that enhance the user experience.