How to Build Forms Using React Hook Form and Yup

Forms are the backbone of nearly every web application, whether you’re creating a login page, a registration form, or a simple contact form. They are essential for gathering user data and ensuring a smooth interaction with your website.

As frontend developers, our mission is to collect this data efficiently, whether it’s sending information to an API, granting access to secure pages post-authentication, or displaying helpful error messages. Ideally, we want to achieve this in a way that is clean, performant, and user-friendly.

Traditional Form Handling in React

Before diving into the magic of React Hook Form and Yup, let’s briefly revisit how we typically handle forms in React without any third-party libraries. Here’s a simple example:

JSX
import React, { useState } from 'react';

const MyFormComponent = () => {
  const [state, setState] = useState({ username: '', email: '', password: '' });

  const handleChange = (event) => {
    const { name, value } = event.target;
    setState(prevState => ({ ...prevState, [name]: value }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log(state);
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Username</label>
        <input type="text" name="username" value={state.username} onChange={handleChange} />
      </div>
      <div>
        <label>Email</label>
        <input type="text" name="email" value={state.email} onChange={handleChange} />
      </div>
      <div>
        <label>Password</label>
        <input type="password" name="password" value={state.password} onChange={handleChange} />
      </div>
      <div>
        <button type="submit">Register</button>
      </div>
    </form>
  );
};

export default MyFormComponent;

In this example, we create a basic registration form with three fields: username, email, and password. While this works, there are some challenges.

Common Pitfalls

  1. Performance Issues: With multiple inputs, each keystroke triggers an update, causing re-renders that can slow down your application.
  2. Code Complexity: As the number of fields grows, so does the complexity of the code. Managing validations and error messages can quickly become overwhelming.

Enter React Hook Form

React Hook Form is a powerful library designed to simplify form management in React. It offers a range of benefits:

  • Lightweight: At just 8.4KB minified and gzipped, it won’t bloat your bundle.
  • Performance: By utilizing refs instead of state for input control, it minimizes unnecessary re-renders.
  • Cleaner Code: You can manage forms with fewer lines, enhancing readability and maintainability.
  • HTML-Centric: Leverage the power of native HTML for your forms.
  • Easy Validation: Integrate with libraries like Yup for schema-based validation.

Getting Started

To start using React Hook Form, install it via npm:

Bash
yarn add react-hook-form

Next, import the useForm hook in your component:

JSX
import { useForm } from 'react-hook-form';

Now, let’s rewrite our registration form using the React Hook Form:

JSX
import React from 'react';
import { useForm } from 'react-hook-form';
import { TextField, Button } from '@material-ui/core';

const MyReactHookFormComponent = () => {
  const { register, handleSubmit } = useForm();

  const submitForm = (data) => {
    console.log({ data });
  };

  return (
    <form onSubmit={handleSubmit(submitForm)}>
      <TextField inputRef={register} name="username" label="Username" />
      <TextField inputRef={register} name="email" label="Email" />
      <TextField inputRef={register} name="password" label="Password" type="password" />
      <Button type="submit">Register</Button>
    </form>
  );
};

export default MyReactHookFormComponent;

With just a few lines of code, we’ve transformed our form handling! Notice how using inputRef={register} simplifies our setup.

Validating with Yup

To add robust validation, we can integrate Yup. First, install Yup and the resolver:

Bash
yarn add yup @hookform/resolvers

Next, create a validation schema:

JSX
import * as yup from 'yup';

export const schema = yup.object().shape({
  username: yup.string().required('Username is required!'),
  email: yup.string().email('Invalid email format!').required('Email is required!'),
  password: yup.string().min(4, 'Password must be at least 4 characters long').required('Password is required!'),
});

Now, you can incorporate the schema into your form:

JSX
import { yupResolver } from '@hookform/resolvers/yup';

const { register, handleSubmit, formState: { errors } } = useForm({
  resolver: yupResolver(schema),
});

And add error messages directly in your form fields:

JSX
<TextField
  inputRef={register}
  name="username"
  label="Username"
  error={!!errors.username}
  helperText={errors.username ? errors.username.message : ''}
 />

Conclusion

React Hook Form, paired with Yup, provides a streamlined approach to building and validating forms in React. With its minimalistic design and powerful features, it enhances both user experience and developer productivity. So, whether you’re tackling a simple contact form or a complex registration process, React Hook Form and Yup have you covered!

Now, get out there and start building forms like a pro!