Clue Mediator

Input validation in React

📅February 5, 2022

In this article, we will show you how to add the validation for form input in React. Here, you will learn how to create a common `Input` component in React and reuse it for multipurpose.

Checkout more articles on ReactJS

Demo Application

Output - Input validation in React - Clue Mediator

Output - Input validation in React - Clue Mediator

Steps to validate the input field in React

  1. Create a react app
  2. Create a common Input component
  3. Create a form using the Input component
  4. Output

1. Create a react app

Let’s create a react application using the `create-react-app`. Here we will add the bootstrap in react.

Reference: How to add Bootstrap in React

2. Create a common Input component

To create a reusable Input component, we need to pass the props like `type`, `name`, `title`, `value`, `onChangeFunc`, etc.

In addition, we have to go through a few more props to handle the validation such as `isReq`, `reqType`, `errorMsg`, `onValidateFunc`.

Input.js

import React, { memo } from 'react';
import PropTypes from 'prop-types';

const getRegExp = (type) => {
  let regx = null;
  switch (type) {
    case 'EMAIL':
      regx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
      break;
    case 'URL':
      regx = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/;
      break;
    default:
      break;
  }
  return regx;
}

const validationHandler = (e, props) => {
  if (!props.onValidateFunc) return;

  const { value, name } = e.target;
  let msg = null;

  if (!value && props.isReq) {
    msg = `Please enter ${props.title}.`;
  } else if (value && props.reqType && !getRegExp(props.reqType).test(value)) {
    msg = `Please enter valid ${props.title}.`;
  }

  props.onValidateFunc(msg, name);
}

const Input = props => {

  const inputProps = {
    name: props.name,
    type: props.type,
    placeholder: props.placeholder || `Enter ${props.title}`,
    className: props.className,
    value: props.value
  }

  return (
    <div class={props.outerClassName}>
      <label class="form-label">{props.title}</label>
      <input {...inputprops}="" onchange="{e" ==""> props.onChangeFunc(e.target.value, e.target.name, e)}
        onBlur={e => validationHandler(e, props)}
      />
      {props.errorMsg && <span class="text-danger">{props.errorMsg === true ? `Please enter ${props.title}.` : props.errorMsg}</span>}
    </div>
  )
}

Input.defaultProps = {
  type: 'text',
  name: '',
  title: '',
  placeholder: '',
  className: 'form-control form-control-sm',
  outerClassName: 'mb-2',
  value: '',
  onChangeFunc: () => { },
  isReq: null,
  reqType: '',
  onValidateFunc: () => { }
}

Input.propTypes = {
  type: PropTypes.string,
  name: PropTypes.string,
  title: PropTypes.string,
  placeholder: PropTypes.string,
  className: PropTypes.string,
  outerClassName: PropTypes.string,
  value: PropTypes.any,
  onChangeFunc: PropTypes.func,
  isReq: PropTypes.bool,
  reqType: PropTypes.string,
  errorMsg: PropTypes.any,
  onValidateFunc: PropTypes.func
}

export default memo(Input);

In the above code, we have used the Regular Expression to validate the input field.

Reference: Regular expression examples in JavaScript

3. Create a form using the Input component

Now it’s time to use the `Input` component in the main component. First of all, we have to define two different state variables called `form` and `error`.

In the error state, we have defined the object for each property. The error object contains the following attributes.

  • `isReq` - For require validation
  • `reqType` - For special type validation such as `EMAIL` and `URL`
  • `errorMsg` - To render the error message on the screen
  • `onValidateFunc` - Function to handle the validation
const [form, setForm] = useState({
  name: '',
  email: '',
  website: ''
});

const onInputValidate = (value, name) => {
  setError(prev => ({
    ...prev,
    [name]: { ...prev[name], errorMsg: value }
  }));
}

const [error, setError] = useState({
  name: {
    isReq: true,
    errorMsg: '',
    onValidateFunc: onInputValidate
  },
  email: {
    isReq: true,
    reqType: 'EMAIL',
    errorMsg: '',
    onValidateFunc: onInputValidate
  },
  website: {
    reqType: 'URL',
    errorMsg: '',
    onValidateFunc: onInputValidate
  }
});

const onInputChange = useCallback((value, name) => {
  setForm(prev => ({
    ...prev,
    [name]: value
  }));
}, []);

Use the following HTML to render the form in React component.

<div class="app">
  <div class="mb-3"><strong>Input validation in React - <a href="https://www.cluemediator.com" target="_blank" rel="noreferrer noopener">Clue Mediator</a></strong></div>
  <div class="form">
    <input name="name" title="Name" value={form.name} onchangefunc={onInputChange} {...error.name}="">
    <input name="email" title="Email" value={form.email} onchangefunc={onInputChange} {...error.email}="">
    <input name="website" title="Website" value={form.website} onchangefunc={onInputChange} {...error.website}="">
    <button class="btn btn-primary btn-sm mt-2" onclick={handleSubmit}>
      Submit
    </button>
  </div>
</div>

Let’s put all code together and see how it looks.

App.js

import React, { useState, useCallback } from 'react';
import Input from './Input';

function App() {

  const [form, setForm] = useState({
    name: '',
    email: '',
    website: ''
  });

  const onInputValidate = (value, name) => {
    setError(prev => ({
      ...prev,
      [name]: { ...prev[name], errorMsg: value }
    }));
  }

  const [error, setError] = useState({
    name: {
      isReq: true,
      errorMsg: '',
      onValidateFunc: onInputValidate
    },
    email: {
      isReq: true,
      reqType: 'EMAIL',
      errorMsg: '',
      onValidateFunc: onInputValidate
    },
    website: {
      reqType: 'URL',
      errorMsg: '',
      onValidateFunc: onInputValidate
    }
  });

  const onInputChange = useCallback((value, name) => {
    setForm(prev => ({
      ...prev,
      [name]: value
    }));
  }, []);

  const validateForm = () => {
    let isInvalid = false;
    Object.keys(error).forEach(x => {
      const errObj = error[x];
      if (errObj.errorMsg) {
        isInvalid = true;
      } else if (errObj.isReq && !form[x]) {
        isInvalid = true;
        onInputValidate(true, x);
      }
    });
    return !isInvalid;
  }

  const handleSubmit = () => {
    const isValid = validateForm();
    if (!isValid) {
      console.error('Invalid Form!');
      return false;
    }

    console.log('Data:', form);
  }

  return (
    <div class="app">
      <div class="mb-3"><strong>Input validation in React - <a href="https://www.cluemediator.com" target="_blank" rel="noreferrer noopener">Clue Mediator</a></strong></div>
      <div class="form">
        <input name="name" title="Name" value={form.name} onchangefunc={onInputChange} {...error.name}="">
        <input name="email" title="Email" value={form.email} onchangefunc={onInputChange} {...error.email}="">
        <input name="website" title="Website" value={form.website} onchangefunc={onInputChange} {...error.website}="">
        <button class="btn btn-primary btn-sm mt-2" onclick={handleSubmit}>
          Submit
        </button>
      </div>
    </div>
  );
}

export default App;

4. Output

Run the application and check the output in the browser.

I hope you find this article helpful.
Thank you for reading. Happy Coding..!! 🙂

Demo & Source Code

GitHub Repository StackBlitz Project