Chinwike Maduabuchi Frontend developer passionate about software engineering.

What’s new in React Hook Form V7

5 min read 1588

React Hook Form V7

Working with forms in React has always been a pain, and developers in the React ecosystem have constantly been working to streamline this tedious task. React Hook Form, one of the many libraries birthed out of this effort, has been proven effective at handling and validating forms. It also equips developers with other tools that improve the developer experience and make building forms more exciting.

From its inception, React Hook Form has been focused on not only serving the end user but also making things easier for developers.

In early April, the React team released a new version of the library, React Hook Form V7. The hot take from this version is that React Hook Form now supports strictly typed forms with the help of TypeScript, which bodes well for the library’s future.

Let’s take a closer look at these newly added features, including:

React Hook Form V7 example

To demonstrate how forms can be strictly typed, we’ll need to create a sample project containing a form with some input fields. If you wish to follow along, you’ll need:

  • A text editor, such as VS code
  • The latest version of Node.js installed on your machine

With those, we can now begin to set up our project.

Because we’ll be using type checking, we need to include TypeScript in project by running the following command in a terminal:

npx create-react-app hook-form --template typescript

This will create a React app named hook-form with TypeScript integrated. It also makes a provision for a tsconfig.json file so you are not required to create one.

Next, add react-hook-form to the project:

npm i react-hook-form

With our example app set up, we’re ready to explore the new features of React Hook Form V7.

We made a custom demo for .
No really. Click here to check it out.

Strictly typed forms in React Hook Form V7

React Hook Form V7 introduces the benefit of static typing into React forms. This feature enables you to write efficient forms with fewer bugs.

To see strictly typed forms in action, open your App.tsx file and replace its contents with the code below:

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

function App() {
  return (
    <form>
      <label htmlFor="firstName">First Name</label>
      <input type="text" />

      <label htmlFor="email">Email</label>
      <input type="email" />

      <label htmlFor="phone">Phone Number</label>
      <input type="number" />

      <label htmlFor="gender"></label>
      <input type="text" />

      <input type="submit" value="submit"/>
    </form>
  );
}
export default App;

Here we created a simple form with a few input fields, brought in the useForm hook from react-hook-form, and extracted the register function from useForm.

To achieve strictly typed forms, we’ll need to declare a type alias (we’ll call it FormValues) above our function body and pass this into useForm as a generic type:

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

function App() {
  const { register } = useForm<FormValues>()

  type FormValues = {
    firstName: string,
    email: string,
    phone: number,
    gender: any
  }

  return (
    // ...
  );
}
export default App;

This alias contains type specifications for the allowed types on each input field.

By passing it into useForm, FormValues now acts as a sort of schema to ensure that the name of any input field correlates with a key in the alias and the values entered into the input fields meet the type specifications.

With this in place, we can now use React Hook Form’s register function to register the input fields we created. But before we register these fields, we should point out the syntax change to the register function in version 7.

Prior to this new release, the syntax used to register an input field in React Form Hook looked like this:

<input type="text" name="firstName" ref={register} />
>

The name of the input field we want react-hook-form to return had to be stored in the HTML 5 name attribute. Although this works fine, it has limitations.

To achieve strict type checking, React Hook V7 takes advantage of TypeScript 4.1 template literals. The register function has been modified to take the name of the input field (as its first argument) and use that to type-check against any alias passed into useForm:

<input type="text" {...register('firstName') />

The following properties would be spread into the input:

const { onChange, blur, ref, name } = register('firstName')

Now let’s use the register function on each field, but we’ll intentionally make a typo on the email input to see how TypeScript reacts:

Typescript Register Function Intentional Typo

The benefits of this feature are undeniable. With strictly typed forms, you can be certain that the right data is being sent to the server by the user and bugs are removed from your code even before runtime. That’s a big win, if you ask me.

Reduced package size

React Hook Form V7 brings reduces the package size by 13 percent. This is owed to the reduced resolver bundle size.

The table below shows the changes in the size of each file:

React Hook V7 Reduce Package Size

Improved performance

The React team went to great lengths to enhance the performance of the React Hook Form library, including introducing a new custom hook and improvements to some existing hooks in the API.

Let us go over these improvements in more detail.

useFormState (new)

The introduction of this new hook allows you to subscribe to individual form state, making each controlled input completely isolated in terms of rerender.

This means that when you need to subscribe to a part of a form, just that part is rerendered with any change to its state and not the entire application from the root level. This isolated render is also applicable to useController and Controller.

For example, say we want to be notified about any input field touched by the user. This is an example of component-level state. We can achieve this with useFormState:

import * as React from "react";
import { useForm, useFormState } from "react-hook-form";

export default function App() {
  const { register, control } = useForm();

  const { touchedFields } = useFormState({control});

  console.log(touchedFields)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName")} />
      <input {...register("lastName")} />

      <input type="submit" />
    </form>
  );
}


// Object logged to the console when user touches the firstName input field
{ firstName: true }

// Object logged when user touches both fields
{ firstName: true, lastName: true }

Each time an input field is touched and an object logged to the console, the existing form state in the other input isn’t altered because the entire application isn’t rerendered.

For useFormState to work, the control object from useForm has to be passed into it because this object contains methods for registering components into react-hook-form.

Using this hook allows for better performance in large and complex form applications. Check out the full list of properties that can be subscribed to with useFormState.

useFieldArray

This custom hook saw no change in its syntax but had improvements behind the scenes. The data structure used in maintaining this hook was enhanced, enabling it to perform faster. It also allows improved focus management, which means you can target any input to focus as long as they expose their ref attribute.

useWatch

useWatch saw an improvement to its watch mechanism, making it easier to subscribe to form changes.

Removed support for IE 11

Like any other forward-thinking community in the tech world, the React team ended support for Internet Explorer 11 with React Hook Form V7. Microsoft itself will stop supporting IE 11 by August 17, 2021, so it’s safe to say we will no longer have to worry about IE 11 in the web development world.

Despite this change, React Hook Form V6 will still be maintained to support IE 11. We’ll discuss details about migrating to the latest version shortly.

New improvements to Resolver

If you’ve used React Hook Form previously, you know about the resolver function and probably know how to use it with validation packages such as Yup. React Hook Form V7 brings new improvements to this API by introducing a third argument to the codebase:

- resolver: (values: any, context?: object) => Promise<ResolverResult> | ResolverResult
+ resolver: (
+   values: any,
+   context: object | undefined,
+   options: {
+     criteriaMode?: 'firstError' | 'all',
+     names?: string[],
+     fields: { [name]: Field } // Support nested fields
+   }
+ ) => Promise<ResolverResult> | ResolverResult

The new options argument gives other libraries insight into the validation process and enables developers to write better custom logic to:

Credit to Joris, a core contributor to the React Hook Form project, for the examples.

React Hook Form V7 also supports other validation libraries, such as Zod, Vest, Joi, and Superstruct.

Asynchronous and synchronous validation options have also been added to the resolver API, with async being the default option. We can switch between the two by using the mode argument:

useForm({ resolver: yupResolver(schema, schemaOptions, { mode: "async" | "sync"}) })

The async option is available in all external validation libraries except Superstruct.

Migrating from React Hook Form V6 to V7

Bill Luo, the creator of React Hook Form, put together a detailed guide to help you migrate your existing V6 applications to React Hook Form V7. The guide includes changes you’ll need to make to your code and other important information you’ll need to make your existing apps work with React Hook Form V7.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Chinwike Maduabuchi Frontend developer passionate about software engineering.

Leave a Reply