@mui v5 Autocomplete with React Hook Form 7 not working?

Viewed 700

I'm working on implementing React Hook Form 7. I have many regular TextFields working, however I am now running in to an issue building out an Autocomplete component. Currently, the dropdown toggle button doesn't display, and none of the options are being rendered in the dropdown list. It acts like a regular TextField. I've looked at many other related S.O. posts like this one, but none seem to be fixing my issue.

import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { validationSchema } from './validationSchema';
import { states, countries } from 'helpers';

const StepTwo: React.FC<Props> = ({ handleNextStep, handlePrevStep }) => {
  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(validationSchema),
    mode: 'onBlur',
    reValidateMode: 'onBlur',
    defaultValues: {
      state: null,
      country: null,
    },
  });

  return (
    <form onSubmit={handleSubmit(handleStepSubmit)} noValidate>
      <Grid item xs={12} className="text-center">
        <Controller
          control={control}
          name="state"
          render={({ field }) => (
            <Autocomplete
              {...field}
              autoComplete
              forcePopupIcon={true}
              fullWidth
              options={states}
              isOptionEqualToValue={(option, value) => option === value}
              renderInput={params => (
                <TextField
                  {...params}
                  error={!!errors?.state}
                  helperText={errors?.state?.message}
                  label="State (Optional)"
                  variant="outlined"
                  size="small"
                  InputProps={{
                    startAdornment: (
                      <InputAdornment position="start">
                        <LocationOnIcon
                          color={errors?.state ? 'error' : 'inherit'}
                        />
                      </InputAdornment>
                    ),
                  }}
                />
              )}
            />
          )}
        />
      </Grid>
      {/* Country Select */}
      <Grid item xs={12} className="text-center">
        <Controller
          control={control}
          name="country"
          render={({ field }) => (
            <Autocomplete
              {...field}
              fullWidth
              options={countries}
              getOptionLabel={item => item}
              isOptionEqualToValue={(option, value) => option === value}
              renderInput={(params: AutocompleteRenderInputParams) => (
                <TextField
                  {...params}
                  error={!!errors?.country}
                  helperText={errors?.country?.message}
                  label="Country (Optional)"
                  variant="outlined"
                  size="small"
                  InputProps={{
                    startAdornment: (
                      <InputAdornment position="start">
                        <PublicIcon
                          color={errors?.country ? 'error' : 'inherit'}
                        />
                      </InputAdornment>
                    ),
                  }}
                />
              )}
            />
          )}
        />
      </Grid>
    </form>
}

states.ts and countries.ts are just arrays of strings with the state and country names. There are no errors in the console. Any idea what I'm doing wrong here?

1 Answers

You're missing to spread the InputProps, so basically you're overwriting all the default properties of your InputProps.

The function signature of the onChange prop of <Autocomplete /> is slightly different. The actual value is the second parameter. Check here for more infos.

<Controller
  control={control}
  name="country"
  render={({ field: { ref, onChange, ...field } }) => (
    <Autocomplete
      {...field}
      onChange={(e, v) => onChange(v)}
      fullWidth
      options={countries}
      isOptionEqualToValue={(option, value) => option === value}
      renderInput={(params) => (
        <TextField
          {...params}
          inputRef={ref}
          error={!!errors?.country}
          helperText={errors?.country?.message}
          label="Country (Optional)"
          variant="outlined"
          size="small"
          InputProps={{
            ...params.InputProps,
            startAdornment: (
              <InputAdornment position="start"></InputAdornment>
            )
          }}
        />
      )}
    />
  )}
/>

Edit ComboBox Material Demo (forked)

Related