💾 React Form Handling & Validation Best Practices: STOP Using `useState`

💾 React Form Handling & Validation Best Practices: STOP Using `useState`

·

6 min read

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:

  1. Minimal Boilerplate: React Hook Form reduces the amount of boilerplate code required to manage forms, making the codebase more concise and maintainable.

  2. Flexible Validation: The library allows you to define custom validation rules and easily integrate with third-party validation libraries.

  3. Performance Optimizations: React Hook Form is designed for performance, minimizing unnecessary re-renders and DOM updates.

  4. Error Handling: The library provides a centralized way to handle and display form validation errors, improving the overall user experience.

  5. Uncontrolled Inputs: React Hook Form supports uncontrolled inputs, which can be more efficient than the traditional controlled input approach.

  6. 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!