Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MUI's Autocomplete AS MULTIPLE input + react-hook-form + controlling default values not working (TypeError: Can't read property 'filter' of undefined)

I am trying to use Material-UI Autocomplete as multiple input with react-hook-form and control the defaultValues of the Autocomplete dynamically (render the component prefilled, when editing data, based on already saved data fetched from a database).

So the main question is:

What is the best way to control the default values in an Material-UI Autocomplete component and use it with react-hook-form?

What i did so far:

  1. With using functions and hooks in react, I have wrapped an Autocomplete component in React Hook Form's Controller to control the state. I tried to implemented the solutions from the docs of MUI and react-hook-form and the solutions of the below threads.

    I created a minimal Sandbox here

What it does

When i set the defaultValue in Controller, it works to display the controlled default value, but throws me an error: TypeError: Cannot read property 'filter' of undefined

  <Controller
      as={
      <Autocomplete
        multiple
        value={defaultValues}
        onChange={(e, values) => setValue("food", values)}
        ...
        renderInput={params => ( ... )}
      />
    }
    control={control}
    name="food"
    defaultValue={defaultValues} // <- this makes the error
  />

When i don't set the defaultValue in Controller, it works perfectly to being able to select multiple values like expected, but it doesn't show the default value.

What is so confusing is, that the Autocomplete has to be controlled with value/onChange and also the Controller has to control with defaultValue/setValue, and it seems they conflict in my case.

  1. It works better when setting defaultValue={ [] } and using a useEffect and controlling the default value only with setValue("food", defaultOption);

    So i created another Sandbox here

  2. Thanks to Bill's answer i refactored the code to a renderProp like proposed in the docs:

    Yet another sandbox here

    Now it works like a charm, but i had to set the onChange prop of the Autocomplete like this:

    onChange={(e, values) => setValue("food", values)}

    instead of what the docs proposed to do: (using the passed onChange)

    onChange={e => props.onChange(e.something)}

    It works, but is this the right way to combine Autocomplete and react-hook-form?

Compare the questions with these threads:

The main difference to the other threads i am trying to do, is to set the defaultValues of a multiple Autocomplete.

Proper way to use react-hook-form Controller with Material-UI Autocomplete

MUI Autocomplete's 'defaultValue' not working when used with Controller of react-hook-form

Why is initial value not set in Material UI Autocomplete using react-hook-form?

The advised solution in the docs of react-hook-form:

https://react-hook-form.com/api/#Controller

And the Code from Material UI docs:

https://material-ui.com/components/autocomplete/#multiple-values

like image 884
vindom Avatar asked Nov 16 '22 07:11

vindom


1 Answers

I was able to get this working by doing the following:

                                <Controller
                                    name='test'
                                    control={control}
                                    render={({onChange, ...props}) => (
                                        <AutoComplete
                                            {...props}
                                            data-testid='test-select'
                                            width={350}
                                            label='Auto Complete'
                                            onChange={onChange}
                                            options={eventTypes}
                                            getOptionLabel={(option) => option ? option.name : ''}
                                            renderOption={(option) => option.name }
                                            getOptionSelected={(option) => option.name}
                                            renderInput={(params) => (
                                                <TextField {...params} error={error} helperText={helperText} label={label} placeholder={label} />
                                            )}
                                            onChange={(e, data) => onChange(data)}
                                            {...props}
                                        />
                                    )}
                                />
like image 177
Dustin Avatar answered Dec 05 '22 20:12

Dustin