How to use React Hook Form with Material UI
Tags: react, webdev
Published: 2020-11-09 16:38:16

[React Hook Form](https://react-hook-form.com/) recently won the **Productity Booster Award** at [React Summit](https://reactsummit.com/) so if you are not familiar with React Hook Form, now is a good time to learn it. React Hook Form is performant, has great docs and it works everywhere (including React Native).

[Material UI](https://material-ui.com/) continues to be the most popular open source React component library out there.

So if you are a React developer, there is a good chance you will find yourself with the opportunity to use Material UI's form components with React Hook Form.

## A basic TextField

If you are working with forms in Material UI, you are most likely working with the [TextField](https://material-ui.com/components/text-fields/) component like this one:

```tsx
import { TextField } from '@material-ui/core';

const BasicTextField = () => {
  return <TextField id="name" helperText="A basic TextField component" />;
};

export default BasicTextField;
```

## Add React Hook Form

If you follow the React Hook Form docs, you will see code that looks like this:

```tsx
<input name="example" ref={register} />
```

This doesn't _quite_ work out of the box with Material UI's `TextField` component. Instead, we need to make use of the `inputRef` prop on `TextField` as demonstrated in this example.

```tsx
import { useState } from 'react';
import { TextField } from '@material-ui/core';
import { useForm } from 'react-hook-form';

interface Inputs {
  name: string;
}

const HookedTextField = () => {
  const [name, setName] = useState<string>();
  const { register, handleSubmit } = useForm<Inputs>();

  const onSubmit = async (data: Inputs) => {
    setName(data.name);
  };

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <TextField inputRef={register} id="name" name="name" helperText="Enter your name and press [Enter]" />
      </form>
      {name && <div>Submitted: {name}</div>}
    </>
  );
};

export default HookedTextField;
```

## Reset the form

Sometimes you need to manually reset form state. React Hook Form makes this easy.

```tsx
const { register, handleSubmit, reset } = useForm<Inputs>();

const onSubmit = async (data: Inputs) => {
  setName(data.name);
  reset();
};
```

## Watch fields

React Hook Form also provides the `watch` function that allows you to immediately respond to changes in form state.

```tsx
const { register, handleSubmit, watch } = useForm<Inputs>();

// This field will update as the user types
const currentName = watch('name');
```

## Putting it all together

```tsx
import { useState } from 'react';
import { TextField } from '@material-ui/core';
import { useForm } from 'react-hook-form';

interface Inputs {
  name: string;
}

const FinalTextField = () => {
  const [name, setName] = useState<string>();
  const { register, handleSubmit, reset, watch } = useForm<Inputs>();

  const currentName = watch('name');

  const onSubmit = async (data: Inputs) => {
    setName(data.name);
    reset();
  };

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <TextField inputRef={register} id="name" name="name" helperText="Enter your name and press [Enter]" />
      </form>
      <div>
        {currentName && <div>Current: {currentName}</div>}
        {name && <div>Submitted: {name}</div>}
      </div>
    </>
  );
};

export default FinalTextField;
```

React Hook Form provides several other options for form management. When paired with Material UI, constructing forms doesn't get much easier.

Are you using React Hook Form with Material UI? [Let me know on Twitter](https://twitter.com/seanconnollydev).