4 ways to use Material UI Select with React Hook Form
Tags: reacthookform, materialui, react, javascript
Published: 2020-10-21 13:46:38

---
title: 4 ways to use Material UI Select with React Hook Form
published: true
description: How to make the Select of MaterialUI works fine with React Hooks Form
tags: reacthookform, materialui, react, javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/ggjs43bqrozfmfxhsdtf.jpg
---

Are you confused in how to make the Select of MaterialUI works fine with React Hooks Form?

## What does not work: use directly the Select component ☹️

The most advantage of use React Hook Form is to get all the benefits of work with uncontrolled components in forms like skip re-rendering and faster mount. But there are some limitations in use some components that are created to work internally like a controlled, this is the case of component Select of Material UI. In this scenario the documentation o React Hook Form indicate to use the Controller component, but there's some other ways to do the Select component work correctly without Controller component.

Lets get started with a simple Select of persons of trinity: Father, Son and Holy Spirit.

```jsx
const trinityPersons = [
	{ value: "father", text: "Father" },
	{ value: "son", text: "Son" },
	{ value: "spirit", text: "Holy Spirit" },
];
```

Let's import some things

```jsx
import { FormControl, TextField, MenuItem } from "material-ui/core";
import { useForm } from "react-hooks-form";
```

## First way: with Textfield component

In this first way is we can save some lines of code only working directly with the **TextField** component and add the **select** prop to made our input work like an select. Now through the prop **inputProps** that Material UI provide to us we can add prop directly to the select input component. Magic!

The next step is check if the **ref** already exist to prevent error and then create our **register** provided by React Hook Form. This is the more shortest way because we prevent to use the Controller and Select component directly.

```jsx
return(
	<FormControl>
		<TextField
		  select
		  label="Choose one Person of trinity"
		  id="trinity"
		  inputProps={{
		    inputRef: (ref) => {
		      if (!ref) return;
		      register({
		        name: "trinityPerson",
		        value: ref.value,
		      });
		    },
		  }}
		>
		 {trinityPersons.map((person) => (
			  <MenuItem key={person.value} value={person.value}>
					{person.text}
				</MenuItem>
			)}
		</TextField>
	</FormControl>
);
```

## Second way: with Select component

This way is the same of the first way, the difference here is that we create using a more explicit syntax provided by Material UI. Now is necessary to import the **Select** and **InputLabel** component.

```jsx
import { InputLabel, Select } from "@material-ui/core";
```

Now we create our FormControl using the Select component:

```jsx
return(
	<FormControl>
		<InputLabel htmlFor="trinity-select">
			Choose one Person of trinity
		</InputLabel>
		<Select
		  id="trinity-select"
		  inputProps={{
		    inputRef: (ref) => {
		      if (!ref) return;
		      register({
		        name: "trinityPerson",
		        value: ref.value,
		      });
		    },
		  }}
		>
		 {trinityPersons.map((person) => (
			  <MenuItem key={person.value} value={person.value}>
					{person.text}
				</MenuItem>
			)}
		</Select>
	</FormControl>
);
```

Even using the the explicit **Select** component we suffer with the way that this component was created, as I said before.

> there are some limitations in use some components that are created to work internally like a controlled

## Third way: with Controller component

This is the way that React Hook Form recommend us. Is the best approach and work like a magic, the Controller component do all the work.

One more thing to import:

```jsx
import { Controller } from "react-hook-form"; 
```

And do not forget do use the control of useForm hook

```jsx
const { register, handleSubmit, control } = useForm();
```

The function of **Controller** component is to wrapper the controlled component and  make it easier for  work with them. It was created to work with Material UI 💖

And now we create our **Select** component inside the **Controller**.

```jsx
return(
<FormControl>
	<InputLabel htmlFor="trinity-select">
		Choose one Person of trinity
	</InputLabel>
	<Controller
    control={control}
    name="trinityPerson"
    as={
      <Select id="trinity-select">
	      {trinityPersons.map((person) => (
				  <MenuItem key={person.value} value={person.value}>
						{person.text}
					</MenuItem>
				)}
      </Select>
    }
  />
</FormControl>
);
```

## Last way: creating a reusable component

And even exist the component way. 

We create an wrapper component that abstract all the boilerplate and expose the use just like an simple Select component. 

```jsx
import FormControl from "@material-ui/core/FormControl";
import InputLabel from "@material-ui/core/InputLabel";
import Select from "@material-ui/core/Select";
import { Controller } from "react-hook-form";

const ReactHookFormSelect = ({
  name,
  label,
  control,
  defaultValue,
  children,
  ...props
}) => {
  const labelId = `${name}-label`;
  return (
    <FormControl {...props}>
      <InputLabel id={labelId}>{label}</InputLabel>
      <Controller
        as={
          <Select labelId={labelId} label={label}>
            {children}
          </Select>
        }
        name={name}
        control={control}
        defaultValue={defaultValue}
      />
    </FormControl>
  );
};
export default ReactHookFormSelect;
```

Now you can use it in your app like this:

```jsx
<ReactHookFormSelect
  id="trinity-select"
  name="trinityPerson"
  label="Choose one Person of trinity"
  control={control}
>
   {trinityPersons.map((person) => (
		  <MenuItem key={person.value} value={person.value}>
				{person.text}
		  </MenuItem>
    )}
</ReactHookFormSelect>
```
---

## Useful links

[https://github.com/react-hook-form/react-hook-form/issues/497](https://github.com/react-hook-form/react-hook-form/issues/497)

[https://github.com/react-hook-form/react-hook-form/issues/380](https://github.com/react-hook-form/react-hook-form/issues/380)

[https://stackoverflow.com/questions/63236951/how-to-use-material-ui-select-with-react-hook-form](https://stackoverflow.com/questions/63236951/how-to-use-material-ui-select-with-react-hook-form)

[https://react-hook-form.com/api#Controller](https://react-hook-form.com/api#Controller)

[https://material-ui.com/components/text-fields/#textfield](https://material-ui.com/components/text-fields/#textfield)