Kikkomann
Kikkomann

Reputation: 416

Material UI's Autocomplete does not show the selected value in React using react-hook-form

I am having issues making Material UI's Autocomplete show the selected item using react-hook-form with options that are objects containing name and id. When I select an item, the box is just empty.

I have a FieldArray of custom MaterialBars which contain a material:

<Controller
  control={control}
  name={`materialBars.${index}.materialId`}
  render={(
    { field: { value, onChange } }
  ) => (
    <Autocomplete
      options={materials.map(material => ({id: material.id, name: material.name})} // materials are fetched from the API
      getOptionLabel={(option) => option.name}
      value={materialItems.find((item) => `${item.id}` === value) || null}
      onChange={(_, val) => onChange(val?.id)}
      renderInput={(params) => <TextField {...params} label="Material" />}
    />
  )}
/>

There is a working example in the codesandbox.

When I select a material in the list, the box is cleared, and the placeholder text is shown instead of the selected material (when focus is removed from the box). The item is selected under the hood, because in my application, when I press submit, the newly selected material is saved to the backend.

I cannot figure out if the issue lies in the react-hook-form part, material UI or me trying to connect the two. I guess it will be easier if the options are just an array of strings with the name of the material (when the form schema has just the materialId), but it is nice to keep track of the id, for when contacting the API.

Upvotes: 1

Views: 883

Answers (1)

Chunbin Li
Chunbin Li

Reputation: 2244

You should set the same type on materialId property between FormValue and ListData.

For Example, if I use number type, it should be

https://codesandbox.io/s/autocomplete-forked-mpivv1?file=/src/MaterialBar.tsx

// App.tsx
const { control, reset } = useForm<FormValues>({
    defaultValues: {
      materialBars: [
        // use number instead of string
        { ..., materialId: 1 },
        { ..., materialId: 6 }
      ]
    }
  });

// util.ts
export const materials = [
  {
    id: 1, // keep it as number type
    ...
  },
  ...
];

// util.ts
export type FormValues = {
  materialBars: {
    // change it from string type to number
    materialId: number;
    ...
  }[];
};
// MaterialBar.tsx
<Controller
  ...
  ) => (
    <Autocomplete
      ...
      /* 
         Remove curly  brackets
           - change`${item.id}` to item.id
      */
      value={materialItems.find((item) => item.id === value) || null}
      
    />
  )}
/>

Upvotes: 2

Related Questions