DEV Community

Cover image for Form Validation In ReactJS by building A Reusable Custom hook⚓
CodeBucks
CodeBucks

Posted on • Updated on • Originally published at devdreaming.com

Form Validation In ReactJS by building A Reusable Custom hook⚓

Hi there👋,

Form📝 handling is an essential part of any website. Since Forms takes the important information from the user. We must create robust form component which can handle inputs and it's validation🚦 easily.

Here, we're going to create a simple React Hook⚓ to handle form as well as it's validation.

The advantage of this hook is,
⏭ It is Reusable, so that you can use it anywhere in your website or for other projects.
⏭ You can handle validation easily, You just have to put conditions for input fields you want to validate.
⏭ This hook makes error handling very easy, also you can customize error messages as well.
⏭ Very easy to implement and build

If you prefer to watch video then here is the video tutorial👇

Let's start coding

First of all makes sure you have created you react app using below command👇

npx create-react-app react-form-component
cd react-form-component
Enter fullscreen mode Exit fullscreen mode

Now start your react app using👇

npm start
Enter fullscreen mode Exit fullscreen mode

1️⃣ Open your project folder in your code editor.

2️⃣ Clear the unnecessary code from the App.js file.

3️⃣ Create form with 3 inputs and 1 submit button like below👇

4️⃣ Add some css in the App.css file

.App {
  text-align: center;
  margin-top: 20vh;
}

form{
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

input{
  margin: 0.5rem 0;
  padding: 1rem;
  outline: none;
}

.submit{
  border: 2px solid #000 !important;
  cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

5️⃣ Create Hooks folder in the Src. In this folder create one file called useForm.js

To create any custom hook, you can keep different file name but name of the hook should always start from use keyword.

Write basic snippet in this file like below,

const useForm = () => {

return();

}

export default useForm
Enter fullscreen mode Exit fullscreen mode

6️⃣ In this hook first we will need two states,

values => A state to store form values, Initially an empty object
errors => A state to store errors if any, Initially an empty object

So let's create these states,

    //Form values
    const [values, setValues] = useState({});
    //Errors
    const [errors, setErrors] = useState({});
Enter fullscreen mode Exit fullscreen mode

7️⃣ Let's create a method to handle form values and set values state.

  //A method to handle form inputs
    const handleChange = (event) => {
        //To stop default events    
        event.persist();

        let name = event.target.name;
        let val = event.target.value;

        validate(event,name,val);
        //Let's set these values in state

        setValues({
            ...values,   //spread operator to store old values
            [name]:val,
        })

    }
Enter fullscreen mode Exit fullscreen mode

This method takes event as an argument and then it will set the values state as [key]:value pair in values object.

Now to use this methods and state in other components we need to return it.

Now your code will look like this👇

8️⃣ Let's call and use this hook in the App.js file.
Open your App file and paste below code.

Import useForm hook.

import useForm from './Hooks/useForm';
Enter fullscreen mode Exit fullscreen mode

Deconstruct states and method from hook.

  //Custom hook call
  const {handleChange, values,errors } = useForm();
Enter fullscreen mode Exit fullscreen mode

Make sure to attach handleChange method with onChange event of each inputs like below👇

<input type="email" name="email" placeholder="E-mail"  onChange={handleChange}   />
<input type="password" name="password" placeholder="password" onChange={handleChange}   />
<input type="text" name="username" placeholder="username"  onChange={handleChange}  />
Enter fullscreen mode Exit fullscreen mode

You can check values state by using console.log(values) inside the App.js file.

Form Validation

9️⃣ Let's create a validation function in useForm hook.

Open useForm.js file, and write below code,

const validate = (event, name, value) => {
    //A function to validate each input values

    switch (name) {
        case 'username':
            if (value.length <= 4) {
                // we will set the error state

                setErrors({
                    ...errors,
                    username: 'Username atleast have 5 letters'
                })
            } else {
// set the error state empty or remove the error for username input

//omit function removes/omits the value from given object and returns a new object
                let newObj = omit(errors, "username");
                setErrors(newObj);

            }
            break;

        default:
            break;
    }
}
Enter fullscreen mode Exit fullscreen mode

Let's break down validate function.

=> This function takes 3 arguments,
event ➡ If you want target element for customization or styling
name ➡ name of the element
values ➡ values of the element

=> Here we have used Switch statement for different elements, so that you can validate different elements.
Key of the switch function is the name of the element.

=> Now for the first case we have username.
So in this case we have a condition that,
if length of the username value is <= 4 then we will set the error state else we will remove that error if exists.

Here we have used omit function, since we can not manipulate state object directly. This omit function takes two arguments first is the object and second is the name of the error you want to remove, Now omit function remove that error if it exist then it returns the new object.

Now in the handleChange method use validate function and make sure to pass all the arguments.

Refer below full code👇

Line no:35 Here for Email I'm using regular expression to validate the email value. If is is false then if condition becomes true and we will set the error accordingly.
Same for the password.
You can customize this regular function as per your requirements.

Line no:82 In this line we can call validate function which will validate all the inputs.

Handle Submit

🔟 Let's create handle submit function.

open App.js file and write below code.

  //Final submit function
  const formLogin = () => {

    console.log("Callback function when form is submitted!");
    console.log("Form Values ", values);
  }
Enter fullscreen mode Exit fullscreen mode

Now this is the function you can customize and will be called when form is submitted.

Pass this function in the useForm hook as a callback function.

  //Custom hook call
  const {handleChange, values,errors,handleSubmit} = useForm(formLogin);
Enter fullscreen mode Exit fullscreen mode

This is how you can pass your custom functions to the hooks.

1️⃣1️⃣ Open useForm.js file.

deconstruct callback function from the props like below👇
const useForm = (callback) => {
...

Let's create handleSubmit function.

    const handleSubmit = (event) => {
        if(event) event.preventDefault();

        if(Object.keys(errors).length === 0 && Object.keys(values).length !==0 ){
            callback();

        }else{
            alert("There is an Error!");
        }
    }
Enter fullscreen mode Exit fullscreen mode

In this function,
If length of errors is 0 and length of values is not zero (values are not empty) then it will call the callback function else it will alert the user.

NOTE: You should customize these conditions as per your requirements.

Don't forget to add handleSubmit function in the return statement.

1️⃣2️⃣ Open App.js file.

Deconstruct handleSubmit method from the useForm hook.
const {handleChange, values,errors,handleSubmit} = useForm(formLogin);

Connect this method with the form like below,


<form onSubmit={handleSubmit}>

Display the Errors

Now to display errors you can do something like this,

      <form onSubmit={handleSubmit}>
      <input type="email" name="email" placeholder="E-mail"  onChange={handleChange}   />
      {
        errors.email && <h3>{errors.email}</h3>
      }
      <input minLength='8' type="password" name="password" placeholder="password"  onChange={handleChange}   />
      {
        errors.password && <h3>{errors.password}</h3>

      }
      <input type="text" minLength='5' required name="username" placeholder="username"  onChange={handleChange}   />
      {
        errors.username && <h3>{errors.username}</h3>

      }
      <input type="submit" value="Submit" className="submit"  />
      </form>
Enter fullscreen mode Exit fullscreen mode

First we will check if there is any error then if it is there then we will display it.

You can watch the video for manipulating some style of the component based on it's values.

The End

That's the end of this tutorial,
I hope it helped you to learn something.

Full Code for this tutorial 👉
https://github.com/codebucks27/React-Form-Component

If you have any question just ask in the comments😉

Thanks For Reading😄

Feel free to visit my youtube channel:

[@codebucks]

Latest comments (7)

Collapse
 
krishnasaini profile image
krishna-saini

the omit function in lodash is obsolete and not in use anymore. read more here - levelup.gitconnected.com/omit-is-b....

Collapse
 
codebucks profile image
CodeBucks

Hey, I think they haven't removed it form the loadash yet. You can still see it in the documentation. Anyway thanks for pointing it out. This article is old and I haven't updated it yet so I will update it soon.

Collapse
 
ourystd profile image
Oury Diallo

Thanks for this article.

I think that this hook can be improved if we can find a way to pass validation function as parameter. What do you think about that ?

Collapse
 
krishnasaini profile image
krishna-saini

why you want to pass validation function as parameter

Collapse
 
codebucks profile image
CodeBucks

When you have multiple forms in your application, then you will need different validations as per the different fields of the forms and it becomes hard to manage if we keep adding validations for all the fields in just one function. That's why it is best to create separate validation functions for separate form then pass it.

Collapse
 
codebucks profile image
CodeBucks

Yeah we can pass validation function just like formLogin. If you have lot's of forms in your website then passing validation function makes more sense.

Collapse
 
codebucks profile image
CodeBucks

Thanks😄