Using React Hook Form with Material UI Select Component

Viewed 3328

I've been having trouble finding the correct way to use React Hook Form with certain Material UI components. I can get it to work with simple Text Fields but when it comes to nested components I can't figure it out.

Specifically, I am trying to submit the data from the selection in a Select component with child MenuItems.

See the notes in the code:

export default function NewGoalPane() {
const classes = useStyles();
const {register, handleSubmit} = useForm(); 

return (
  <div className={classes.root}>
    <CssBaseline />
    <form noValidate onSubmit={handleSubmit((data) => alert(JSON.stringify(data)))}>
      <main className={classes.content}>
        <div className={classes.text_field_section}>

          //This text field works and React Hook Form reads the data correctly.
          <TextField
            label="Goal Title"
            name="goalTitle"
            defaultValue=""
            inputRef={register}/>
        </div>

        //This Select component does not read the data from the selection of the MenuItems.
        <div className={classes.section}>
          <Select
            label="Repeating"
            name="repeating"
            defaultValue={true}
            inputRef={register} // Here I call register like all the React Hook Form docs say
          >
            <MenuItem value={true}>Yes</MenuItem>
            <MenuItem value={false}>No</MenuItem>
          </Select>
        </div>
      </main>
    </form>
  </div>
);

}

How do I fix the Select component so that React Hook Form collects the data in the form submission?

2 Answers

I found Material UI's TextField simple as it requires less code and also you can avoid using controller and Select component. This is my solution.

<TextField
  select
  name: 'city'
  inputRef={register({ required: true })}
  onChange={e => setValue('city', e.target.value, {shouldValidate: true})}
  label="City"
  defaultValue="">
  {cityList.map((option, index) => (
    <MenuItem key={index} value={option}>
      {option}
    </MenuItem>
  ))}
</TextField>

{errors.city && <ErrorText>City is required</ErrorText>}

If you are using v7 the best way was to use controllers for Material Ui components

import { useForm, Controller } from 'react-hook-form';


//component

const methods = useForm();
const { control } = methods;

<Controller
  name="city"
  control={control}
  defaultValue=""
  rules={{ required: 'City Required' }}
  render={({ field: { onChange, value } }) => (
        <TextField
          fullWidth
          label="City"
          variant="outlined"
          value={value}
          onChange={onChange}
        />
      )}
 />
   
Related