Creating a Responsive Form Validation in React

In this tutorial, we will learn how to create a responsive form validation in React. Form validation is an essential part of any web application as it ensures that the data submitted by the user is valid and meets the required criteria. React is a popular JavaScript library used for building user interfaces, and it provides a straightforward way to handle form validation efficiently.

creating responsive form validation react

Introduction

Form validation is the process of checking whether the data entered by the user in a form meets the specified criteria. It helps in preventing invalid data from being submitted and ensures the integrity of the data stored in the application. React is a JavaScript library developed by Facebook that allows developers to build reusable UI components. It provides a declarative syntax for creating interactive user interfaces.

Setting up the Project

To get started, we need to create a new React project and install the necessary dependencies. Follow the steps below to set up the project:

Creating a new React project

First, we need to create a new React project using the create-react-app command. Open your terminal and run the following command:

npx create-react-app form-validation

This command will create a new directory called form-validation and set up a basic React project structure inside it.

Installing necessary dependencies

Next, we need to install some additional dependencies for form validation. Navigate to the project directory and run the following command:

cd form-validation
npm install formik yup

We will be using the Formik library for managing form state and validation, and the Yup library for defining validation schemas.

Building the Form Component

Now that we have set up our project, let's start building the form component. We will create a new file called Form.js inside the src directory and add the following code:

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

const Form = () => {
  const formik = useFormik({
    initialValues: {
      name: '',
      email: '',
      password: '',
    },
    validationSchema: Yup.object({
      name: Yup.string()
        .required('Name is required'),
      email: Yup.string()
        .email('Invalid email address')
        .required('Email is required'),
      password: Yup.string()
        .min(6, 'Password must be at least 6 characters')
        .required('Password is required'),
    }),
    onSubmit: (values) => {
      alert(JSON.stringify(values, null, 2));
    },
  });

  return (
    <form onSubmit={formik.handleSubmit}>
      <div>
        <label htmlFor="name">Name</label>
        <input
          type="text"
          id="name"
          name="name"
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.name}
        />
        {formik.touched.name && formik.errors.name && (
          <div>{formik.errors.name}</div>
        )}
      </div>
      <div>
        <label htmlFor="email">Email</label>
        <input
          type="email"
          id="email"
          name="email"
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.email}
        />
        {formik.touched.email && formik.errors.email && (
          <div>{formik.errors.email}</div>
        )}
      </div>
      <div>
        <label htmlFor="password">Password</label>
        <input
          type="password"
          id="password"
          name="password"
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.password}
        />
        {formik.touched.password && formik.errors.password && (
          <div>{formik.errors.password}</div>
        )}
      </div>
      <button type="submit">Submit</button>
    </form>
  );
};

export default Form;

In the above code, we import the necessary dependencies and define our form component. We use the useFormik hook from Formik to manage the form state and validation. The initialValues object defines the initial values for the form fields. The validationSchema object defines the validation rules using Yup. The onSubmit function is called when the form is submitted and alerts the form values.

Inside the return statement, we render the form elements and bind them to the formik state using the formik.handleChange, formik.handleBlur, and formik.values properties. We also display the error messages using conditional rendering based on the formik.touched and formik.errors properties.

Handling Form Submission

Now that we have set up our form component, let's implement the logic to handle form submission. Modify the onSubmit function in the Form.js file as follows:

onSubmit: async (values, { resetForm }) => {
  // Simulate form submission
  await new Promise((resolve) => setTimeout(resolve, 1000));
  
  // Display success message
  alert('Form submitted successfully');

  // Reset the form
  resetForm();
},

In the above code, we simulate the form submission by adding a delay of 1 second using setTimeout. After the delay, we display a success message using the alert function. Finally, we reset the form using the resetForm function provided by Formik.

Styling the Form

To style our form, we can use CSS frameworks like Bootstrap or Tailwind CSS. Let's use Bootstrap for this tutorial. Follow the steps below to add Bootstrap to your project:

Using CSS frameworks

First, install Bootstrap by running the following command in your terminal:

npm install bootstrap

Next, import the Bootstrap CSS file in the index.js file of your project:

import 'bootstrap/dist/css/bootstrap.css';

Now, you can use Bootstrap classes to style your form. Modify the Form.js file as follows:

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

const Form = () => {
  // Formik code...

  return (
    <form onSubmit={formik.handleSubmit}>
      <div className="form-group">
        <label htmlFor="name">Name</label>
        <input
          type="text"
          id="name"
          name="name"
          className="form-control"
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.name}
        />
        {formik.touched.name && formik.errors.name && (
          <div className="text-danger">{formik.errors.name}</div>
        )}
      </div>
      {/* Other form fields */}
      <button type="submit" className="btn btn-primary">Submit</button>
    </form>
  );
};

export default Form;

In the above code, we use the form-group class for each form field container and the form-control class for the input elements. We also use the text-danger class to style the error messages.

Testing and Debugging

To ensure the correctness of our form validation logic, we need to write unit tests and debug any issues that may arise. Let's see how we can accomplish this:

Writing unit tests

Formik provides a testing utility called render that allows us to render our form component and interact with it in our tests. Create a new file called Form.test.js inside the src directory and add the following code:

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Form from './Form';

test('submitting form with valid data', () => {
  render(<Form />);

  // Fill in the form fields
  const nameInput = screen.getByLabelText('Name');
  fireEvent.change(nameInput, { target: { value: 'John Doe' } });

  const emailInput = screen.getByLabelText('Email');
  fireEvent.change(emailInput, { target: { value: '[email protected]' } });

  const passwordInput = screen.getByLabelText('Password');
  fireEvent.change(passwordInput, { target: { value: 'password123' } });

  // Submit the form
  fireEvent.click(screen.getByText('Submit'));

  // Check if success message is displayed
  expect(screen.getByText('Form submitted successfully')).toBeInTheDocument();
});

In the above code, we use the render function from @testing-library/react to render our form component. We then use the getByLabelText function to get the input elements and the fireEvent function to simulate user interactions. Finally, we use the getByText function to check if the success message is displayed.

Debugging form validation issues

If you encounter any issues with your form validation logic, you can use the debugging capabilities provided by React and Formik. You can use the console.log function to log the values of the formik state and the validation errors at different stages of your form component's lifecycle. This will help you identify any issues and debug them effectively.

Conclusion

In this tutorial, we learned how to create a responsive form validation in React. We set up a new React project, installed the necessary dependencies, and built a form component using Formik and Yup. We implemented form validation logic, displayed error messages, and handled form submission. We also styled our form using Bootstrap and learned how to write unit tests and debug form validation issues.

Form validation is an essential aspect of web development, and React provides a convenient way to handle it. By following the steps outlined in this tutorial, you can create robust and user-friendly forms for your React applications.