Checkout the original post to read with Table of Contents
Learn React with The Complete React Bootcamp only for $49 a year (Free 1 month trial) *affiliate link
Handling and validation form in React is an essential part of when developing a web application. It ensures that user inputs meet the necessary criteria before they are submitted.
In React, there are multiple ways to handle form validation, using the built-in state management (useState
), useRef
and specialized libraries such as React Hook Form.
In this article, we will explore best practices for handling and validating forms in React, both with and without using external libraries.
Related Posts
Handling & Validating Form without Library
Why you should stop using useState
for input handling
While useState
is a straightforward way to manage form inputs in React, it has some performance drawbacks
Each time a form field is updated, the component re-renders, which can be costly, especially in larger forms with many fields.
This re-rendering can lead to laggy user experiences, particularly on slower devices or browsers.
Additionally, managing state for each input field can become cumbersome and error-prone, leading to more complex and less maintainable code.
While useState
is suitable for simple forms, for more complex forms with multiple validation rules, it’s worth exploring more efficient alternatives.
Performant way to handle form using useRef
For more complex forms, useRef
provides a more performant way to handle form. Unlike useState
, useRef
doesn’t trigger a component re-render when its value changes.
This makes it ideal for scenarios where you need to track form values without affecting the component's rendering.
Consider a profile settings form that includes multiple types of inputs, such as text, email, and password fields.
Using useRef
, you can manage the form values and validations efficiently:
import React, { useEffect, useRef } from 'react';
export const ProfileForm = () => {
const formRef = useRef(null);
useEffect(() => {
const { name } = formRef.current;
name.value = "pre-filled name"
}, [])
const handleSubmit = (e: any) => {
e.preventDefault();
// Validate the form
if (formRef.current) {
const { name, email, password } = formRef.current;
// Perform validation checks
if (!name.value.trim()) {
alert('Please enter your name.');
return;
}
if (!email.value.trim() || !email.value.includes('@')) {
alert('Please enter a valid email address.');
return;
}
if (password.value.length < 8) {
alert('Password must be at least 8 characters long.');
return;
}
// If all validation passes, submit the form
console.log('Form submitted:', {
name: name.value,
email: email.value,
password: password.value,
});
}
};
return (
<form ref={formRef} onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input type="text" id="name" name="name" />
</div>
<div>
<label htmlFor="email">Email:</label>
<input type="email" id="email" name="email" />
</div>
<div>
<label htmlFor="password">Password:</label>
<input type="password" id="password" name="password" />
</div>
<button type="submit">Submit</button>
</form>
);
};
By using useRef
, we can directly access the form field values without the need to maintain separate state variables. Beside more performant, you also need less codes because you dont have to implement onChange
in every input field.
Additionally, the useRef
approach makes it easier to handle complex validation logic, as you can directly interact with the form fields and perform validations without relying on the React state management system.
Handling and Validating Form with React Hook Form
While the useRef
approach is a powerful and performant way to handle form validation in React, there are times when using a dedicated library can be beneficial.
One such library is React Hook Form.
When your form requirements become more complex, or you need to manage more advanced validation scenarios, React Hook Form provides robust solutions and comprehensive set of features without sacrificing performance.
React Hook Form itself use useRef
under the hood for tracking input change, but also using useState
for form validation and dirty state.
Here's an example of how you can use React Hook Form to implement the same profile form with validation:
import React from 'react';
import { useForm } from 'react-hook-form';
const ProfileForm = () => {
const {
register,
handleSubmit,
formState: { errors }
} = useForm();
const onSubmit = (data) => {
// Submit the form data
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor='name'>Name:</label>
<input type='text' id='name' {...register('name', { required: true })} />
{errors.name && <div>Name is required</div>}
</div>
<div>
<label htmlFor='email'>Email:</label>
<input type='email' id='email' {...register('email', { required: true, pattern: /\S+@\S+\.\S+/ })} />
{errors.email && <div>Invalid email address</div>}
</div>
<div>
<label htmlFor='password'>Password:</label>
<input type='password' id='password' {...register('password', { required: true, minLength: 8 })} />
{errors.password && <div>Password must be at least 8 characters long</div>}
</div>
<button type='submit'>Submit</button>
</form>
);
};
In this example, we use the useForm
hook provided by React Hook Form to manage the form state and validation.
The register
function is used to register each form field with the library, and the formState.errors
object is used to display validation error messages.
One of the key advantages of using React Hook Form is that it provides a more declarative approach to form validation, allowing you to define validation rules directly in the register
function.
This can make the code more readable and easier to maintain, especially for complex forms.
React Hook Form Features
React Hook Form offers several features that make it a powerful choice for form validation in React:
Minimal Boilerplate: React Hook Form reduces the amount of boilerplate code required to manage forms, making the codebase more concise and maintainable.
Flexible Validation: The library allows you to define custom validation rules and easily integrate with third-party validation libraries.
Performance Optimizations: React Hook Form is designed for performance, minimizing unnecessary re-renders and DOM updates.
Error Handling: The library provides a centralized way to handle and display form validation errors, improving the overall user experience.
Uncontrolled Inputs: React Hook Form supports uncontrolled inputs, which can be more efficient than the traditional controlled input approach.
Integrations: The library integrates well with other popular React libraries, such as React Router and Yup (for schema validation).
Conclusion
Choosing the right approach for form validation in React can significantly impact the performance and maintainability of your application. While useState
works well for simple forms, leveraging useRef
and React Hook Form offers better performance and flexibility for more complex forms.
Ultimately, the choice between these approaches will depend on the specific requirements of your project, the complexity of your forms, and your team's familiarity with the different techniques.
By understanding the strengths and weaknesses of each approach, you can make an informed decision and implement effective form validation in your React applications.
What do you thinK? Do you have any other way to handling and validating form in React project?
Feel free to share it in the comment below :smile:
Please give it a like or share if you find this article helpful. Happy coding!