Form validation with react using debounce function

In this tutorial, We will build a sample react application to demonstrate form input validation using debounce function. Using the debounce function approach ensures that the user is given instant feedback that a field is invalid while also improving performance by preventing the bottleneck of calling a validation function that fire’s too frequently on every onChangeinput event.

Let’s set up the project

For this tutorial, I will be using create-react-app a Facebook tool that can scaffold a react app quickly.

npx create-react-app react-sample-validation-debounce

Go to your terminal and install the following packages.

npm i prop-types lodash.debounce validatorjs
  • prop-types: Provides type checking for React props and similar objects.
  • lodash.debounce: Creates a debounced function that delays invoking function until after specified milliseconds have elapsed since the last time the debounced function was invoked
  • validatorjs: A Javascript validation library that makes validation very easy.

We will be using bootstrap for our forms, so go to the index.html in your public directory and paste the bootstrap cdn above the title tag in the head section.

<link href=”" rel=”stylesheet”/>

Let’s build the form

To build the form we will be validating, we will first build a TextField component that will accept props which will determine the name, type , value, placeholder, class, title and onChangefunction of an input field. The TextField component will also determine how each of the form input will look like if their input value is valid or invalid by adding the is-invalid class to the input field and a span tag with a class name ofinvalid-feedback if the input value is invalid

Create a file named TextField.jsx and paste the below code in it.

Edit the App.js file to App.jsx for consistency since we will like to name all of our react components file with the .jsx extension. The App.jsx file will contain our main component that will display our form and make use of other utils function to build and validate our form. Paste the code below in the App.jsx file.

The App.jsx file contains the following code logic.

  • The component state that contains the formCredentials (keeps track of the form input values) and the formErrors (holds the validation message of each of the form input).
  • The render function where we create our form using the TextField component we created above.
  • The onChange function that is called whenever a user types in each of the input fields.
  • The onSubmit function that is triggered when the user submits the form. We will handle the submit function later as it currently just logs a message on the console when a user submits the form.

Paste the CSS code below in the index.css file to vertically center our form in the browser.

html, body{
.vertical-center {
min-height: 100%; /* Fallback for browsers do NOT support vh unit */
min-height: 100vh; /* These two lines are counted as one */
display: flex;
align-items: center;

Let’s validate the form

For the form validation, we will be using validatorjs one of the packages we installed when setting up this project.

Create a folder named utils and also a file named validation.js inside of the utils folder. We are going to place our validation functions in this file. Paste the code below in the validation.js file.

Things to note in the validation.js file.

  • The rules object contains all the validation rules for the form
  • The singleFieldValidation function picks out the rule for a particular input field and validates its value against it.
  • I added the allFieldsValidation to handle validation of the whole form inputs when submitting the form.

Time to go back to the App.js file to handle form inputs validation. Import the lodash.debounce and and validation.js functions to the App.js file.

import debounce from 'lodash.debounce'
import {singleFieldValidation, allFieldsValidation} from "./utils/validation";

Place the variable waitTime with value in milliseconds above the class declaration. I have chosen to use 500ms. As the user types, the input event will get ignored until the user stops typing for the specified wait time in milliseconds.

const waitTime = 500;

Update the onChange and onSubmit function in the App component.

  • In the onChange function, we added the code below to validate a field input.
this.debounceSingleFieldValidation({name, value});
  • The handleSubmit function validates all of the form inputs and then set the state of the component with errors received from allFieldsValidation(this.sate.formCredentials) called if the form contains an error or alert message "No error, form can now submit..." if the form inputs are all valid.
  • The debounceSIngleFieldValidation function creates a debounced function that delays invoking func (the function that handles input field validation and sets the formErrors state based on validation result) until after waitTime milliseconds have elapsed since the last time the debounced function was invoked.

What we’ve achieved here is that as the user types, validating the input field will get ignored until the user stops typing for waitTime ms in our case 500ms. When 500 ms elapses since the last keystroke (or some other input action), the filed validation will finally be triggered.

Run the app by typing the command npm startin your terminal. This launches the app on your default browser on http://localhost:3000. You can find a working demo of our work here.

NB: You can choose to use any validation package you wish to use or even write your own validation functions and everything will still work, what’s important is that the returned result from the two functions in the validation.js file follows the pattern below.
isValid: false, // boolean value,
errors: [] // array of strings

You can follow the same pattern used in this tutorial to validate your forms on input change without worrying about the speed users of your app fill input fields not only in your react applications but also in other frontend frameworks. The source code for this tutorial is on GitHub.