Search code examples
material-ui

Material UI Autocomplete - warning: A props object containing a "key" prop is being spread into JSX


So I am using the Material UI Autocomplete component with Next.js, and receiving this warning that I tried to resolve but could not. Is the error from renderInput function? If so there is no "key" property in "...params" , so I can not remove like the warning message suggest.

How I can fix this?

const top100Films = ['a', 'b', 'c', 'd'];

// props.tags = ['a', 'c']

<Autocomplete
  multiple
  id="tags-outlined"
  onChange={(event: any, newValue: string[]) => {
    props.onTagsChange(newValue);
  }}
  options={top100Films}
  value={props.tags}
  filterSelectedOptions
  renderInput={(params) => (
    <TextField
      {...params}
      label="Tags"
      placeholder="Tag"
    />
  )}
/>

enter image description here

hydration-error-info.js?32aa:26 Warning: A props object containing a "key" prop is being spread into JSX:
  let props = {key: someKey, tabIndex: ..., role: ..., id: ..., onMouseOver: ..., onClick: ..., onTouchStart: ..., data-option-index: ..., aria-disabled: ..., aria-selected: ..., className: ..., children: ...};
  <li {...props} />
React keys must be passed directly to JSX without using spread:
  let props = {tabIndex: ..., role: ..., id: ..., onMouseOver: ..., onClick: ..., onTouchStart: ..., data-option-index: ..., aria-disabled: ..., aria-selected: ..., className: ..., children: ...};
  <li key={someKey} {...props} />

Solution

  • The problem is due to how nextjs renders its components. Specifically, it is due to improper key setting for the list of options and tags in Autocomplete component. Although it is quite tedious, you have to explicitly state the keys of tags and options using below.

    You could use renderOption and renderTags provided by Autocomplete to fix this issue.

      renderOption={(props, option) => {
        return (
          <li {...props} key={option}>
            {option.label}
          </li>
        );
      }}
    

    And

        renderTags={(tagValue, getTagProps) => {
          return tagValue.map((option, index) => (
            <Chip {...getTagProps({ index })} key={option} label={option} />
          ))
        }}
    

    So... in your case it would become:

      <Autocomplete
        multiple
        id="tags-outlined"
        options={top100Films}
        onChange={(event: any, newValue: string[]) => {
          props.onTagsChange(newValue);
        }}
        value={props.tags}
        filterSelectedOptions
        renderOption={(props, option) => {
          return (
            <li {...props} key={option}>
              {option}
            </li>
          )
        }}
        renderTags={(tagValue, getTagProps) => {
          return tagValue.map((option, index) => (
            <Chip {...getTagProps({ index })} key={option} label={option} />
          ))
        }}
        renderInput={(params) => (
          <TextField
            {...params}
            label="Tags"
            placeholder="Tag"
          />
        )}
      />
    

    You could read more about renderOption and renderTags here.

    PS. Don't forget to import Chip from Mui!