ant-design: Option of AutoComplete Select should not use value as a key, as value may not be unique and React requires keys to be unique

  • I have searched the issues of this repository and believe that this is not a duplicate.

Version

3.8.4

Environment

Chromium 68.0.3440.75, Firefox ESR 52.9.0

Reproduction link

Edit on CodeSandbox

Steps to reproduce

Use Select component and pass key and value properties to its Select.Options. Make sure that there are two same value values. Notice warning about duplicate keys in the browser’s console.

What is expected?

key property in Select.Option component is used as component key.

What is actually happening?

value property is being used as component key instead.


One can notice the bug while looking at https://github.com/ant-design/ant-design/blob/3.8.4/components/select/index.tsx, the Select.Option and Select.OptGroup components does not support key property as one could expect after reading documentation.

export interface OptionProps {
  disabled?: boolean;
  value?: string | number;
  title?: string;
  children?: React.ReactNode;
}

export interface OptGroupProps {
  label?: React.ReactNode;
}

That issue was raised before in #11074.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (5 by maintainers)

Most upvoted comments

I don’t know what component you should use but probably you need Select[showSearch], you can checkout it. But still, value of AutoComplete should not be duplicated.

@afc163 this case does require re-opening

https://codesandbox.io/s/61875yq9xr

@afc163 your example does not work in the following situation:

const data = [
  { id: "1", title: "sun", subtitle: "1" },
  { id: "2", title: "sun", subtitle: "2" },
  { id: "3", title: "sun", subtitle: "3" }
];
...
<AutoComplete optionLabelProp="value">
  {data.map(({ id, title, subtitle }) => (
    <Option key={id} value={title}>
      <p>{title}</p>
      <p>{subtitle}</p>
    </Option>
  ))}
</AutoComplete>

so i consider it’s a bug and the easiest way to solve it is to let pass your own key for option

upd: You even have this bug in your own documentation page 😃

image

This still appears to be a problem. I can set a key prop on <AutoComplete.Option>, however as soon as I set a value prop this is used as the key.

I understand that value should not be duplicated, but in some cases this is not avoidable, for example when using a Belgian zip code API, where multiple towns can have the same zip code.

Thanks, so I should use AutoComplete instead? Why shouldn’t we support passing key to make sure that it’s unique?

I’m hitting this same issue. Two AutoComplete.Options cannot have the same value, even though their keys are unique.

Did anyone come up with a workaround? I can’t tell why this issue was closed.

I found a workaround.

const options = [
    {'value' = 'sometest.com - somecategory1', 'realValue' = 'sometest.com', 'category' = 'somecategory1},
    {'value' = 'sometest.com - somecategory2', 'realValue' = 'sometest.com', 'category' = 'somecategory2'},
    {'value' = 'sometest.com - somecategory3', 'realValue' = 'sometest.com', 'category' = 'somecategory3'}
];

onDomainSelect = (value, option, form) => {
    form.change('domain', option.realValue);
    form.change('category', option.category);
}

form - is a final-form instance

PS: I just noticed it’s like the same as previous… oops )

https://codesandbox.io/s/61875yq9xr

@afc163 your example does not work in the following situation:

const data = [
  { id: "1", title: "sun", subtitle: "1" },
  { id: "2", title: "sun", subtitle: "2" },
  { id: "3", title: "sun", subtitle: "3" }
];
...
<AutoComplete optionLabelProp="value">
  {data.map(({ id, title, subtitle }) => (
    <Option key={id} value={title}>
      <p>{title}</p>
      <p>{subtitle}</p>
    </Option>
  ))}
</AutoComplete>

so i consider it’s a bug and the easiest way to solve it is to let pass your own key for option

upd: You even have this bug in your own documentation page 😃

image

Agreed! I am dealing with the same issue. I have to set the value property explicitly because I am showing a custom Option as follows:

const _materials = [
   { value: '3" Nails', type: "5lb Box", color: "N/A" },
   { value: '3" Nails', type: "", color: "N/A" },
   { value: "B & B", type: "", color: "" },
   { value: "Caulk", type: "Solar Seal", color: "" },
   { value: "Caulk", type: "", color: "" },
   { value: "Caulk", type: "Flintbond", color: "N/A" },
   ...
];

const options = _materials.map((m) => (
    <Option
      key={JSON.stringify(m)}
      value={m.value}
      type={m.type}
      color={m.color}
      style={{ borderBottom: "1px solid #f0f0f0" }}
    >
      <div>
        <b>{m.value}</b>
      </div>
      {m.type && (
        <div style={m.color ? { width: "50%", display: "inline-block" } : {}}>
          Type: {m.type}
        </div>
      )}
      {m.color && (
        <div style={m.type ? { width: "50%", display: "inline-block" } : {}}>
          Color: {m.color}
        </div>
      )}
    </Option>
  ));

In this scenario I have several options and some of them may have the same value but will not share the same type or color.

I have seen it suggested to others to use a Select instead but the issue is this list is not all inclusive nor is it possible to ever get an all inclusive list for this scenario so the user has to have the ability to select/type values that do not exist in the list itself.