react-hook-form & material-UI Select

6.4k views Asked by At

I am having an issue getting the following code to work with react-hook-form.

I am wondering if anyone knows of a solution so that when I hit submit it submits it. The error is saying there is no name property, however you will see the code does have a name property value

  const { register, handleSubmit, errors } = useForm();

  const onSubmit = data => console.log(data);

  
return(
<form onSubmit={handleSubmit(onSubmit)} className={classes.container}>
         
 <TextField fullWidth   
                    onChange={changeBudget}
                    inputRef={register({ required: true })}
                    id="select" 
                    name="campaignSpend" 
                    label="Campaign Budget" 
                    value={campaignBudget}
                    select variant="outlined">
                      <MenuItem value="250">$250</MenuItem>
                      <MenuItem value="500">$500</MenuItem>
                      <MenuItem value="$1000">$1000</MenuItem>
                    </TextField>

                <Button className={classes.button} type="submit" variant="outlined" aria-label="delete" color="primary" >
                  Continue
                </Button>

 </form>
)

I also tried


<FormControl className={classes.formControl} component="fieldset" inputRef={register({ required: true })}>
                      <InputLabel id="demo-controlled-open-select-label">Campaign Budget</InputLabel>
                      <Select
                        labelId="demo-controlled-open-select-label"
                        id="demo-controlled-open-select"
                        name="test"
                        open={open}
                        onClose={handleClose}
                        onOpen={handleOpen}
                        value={campaignBudget}
                        onChange={changeBudget}
                   
                      >
                        <MenuItem value="">
                          <em>None</em>
                        </MenuItem>
                        <MenuItem value={10}>Ten</MenuItem>
                        <MenuItem value={20}>Twenty</MenuItem>
                        <MenuItem value={30}>Thirty</MenuItem>
                      </Select>
                    </FormControl>
4

There are 4 answers

0
DesignMonkeyJim On BEST ANSWER

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

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

//component

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

 <FormControl fullWidth variant="outlined">
            <InputLabel htmlFor="campaign_budget_label">Campaign Budget</InputLabel>
            <Controller
              name="campaignSpend"
              control={methods.control}
              rules={{ required: 'Budget Required' }}
              render={({ field: { onChange, value} }) => (
                <Select 
                  value={value}
                  onChange={onChange}
                  label="Campaign Budget" 
                  labelId="campaign_budget_label"
                  >
                  <MenuItem value="250">$250</MenuItem>
                  <MenuItem value="500">$500</MenuItem>
                  <MenuItem value="$1000">$1000</MenuItem>
                </Select>
              )} 
              defaultValue="" // make sure to set up defaultValue
            />
          </FormControl>
1
RussellHarrower On

Solution for me was:

 <Controller
                          as={<TextField fullWidth  className={classes.textField}
                           variant="outlined" id="select" value="20" select>
                              <MenuItem value={250}>$250</MenuItem>
                              <MenuItem value={500}>$500</MenuItem>
                              <MenuItem value={1000}>$1000</MenuItem>
                            </TextField>
                          }
                          label="Campaign Budget"
                          name="campaignBudget"
                          defaultValue="250"
                          control={control}
                        />

Note that I had to use TextField for the label to work.

0
Krishna Nigalye On

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>}
0
paulin-crtn On

Here is my solution with react-hook-form (version 7) and @mui/joy (version 5-alpha). No useState or useEffect needed.

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

const { control, setValue } = useForm();

<Controller
  name="smartphone"
  control={control}
  rules={{ required: true }}
  defaultValue="" // Avoid error "A component is changing the uncontrolled value state to be controlled."
  render={({ field: { onChange, ...field } }) => (
    <Select
      onChange={(event) => {
        setValue(
          "smartphone",
          (event?.target as HTMLInputElement).ariaLabel as string
        );
      }}
      {...field}
    >
      {smartphones.map((smartphone) => (
        <Option
          key={smartphone.id}
          value={smartphone.id}
          aria-label={smartphone.id}
        >
          {smartphone.name}
        </Option>
      ))}
    </Select>
  )}
/>