1

I have this Dropdown menu instance:

      <Dropdown
        selection
        options={this.state.options}
        search
        value={value}
        onChange={this.handleChange}
        onSearchChange={this.handleSearchChange}
      />

and when my backend returns response, which is then set as state and it is structured like this:

"options": [
    {
      "text": "New York,All Airports (NYC) , USA",
      "value": "NYC"
    },
    {
      "text": "New York,Newark Liberty Intl (EWR), USA",
      "value": "EWR"
    },
    {
      "text": "New York,John F Kennedy (JFK), USA",
      "value": "JFK"
    },
    {
      "text": "New York,La Guardia (LGA), USA",
      "value": "LGA"
    }
  ]

...I get this warning:

Warning: flattenChildren(...): Encountered two children with the same key, 1:$BLZ. Child keys must be unique; when two children share a key, only the first child will be used.

in select (created by Dropdown)
in div (created by Dropdown)
in Dropdown (created by SearchForm)

How do I add keys to these elements to prevent this warning?

0

1 Answer 1

2

So looking at the code for the Semantic UI source for the dropdown component, the render options function converts your passed in options into a array of DropdownItem components:

renderOptions = () => {
    const { multiple, search, noResultsMessage } = this.props
    const { selectedIndex, value } = this.state
    const options = this.getMenuOptions()

    if (noResultsMessage !== null && search && _.isEmpty(options)) {
      return <div className='message'>{noResultsMessage}</div>
    }

    const isActive = multiple
      ? optValue => _.includes(value, optValue)
      : optValue => optValue === value

    return _.map(options, (opt, i) => (
      <DropdownItem
        key={`${opt.value}-${i}`}
        active={isActive(opt.value)}
        onClick={this.handleItemClick}
        selected={selectedIndex === i}
        {...opt}
        // Needed for handling click events on disabled items
        style={{ ...opt.style, pointerEvents: 'all' }}
      />
    ))
  }

the key for this array is set by taking the value prop and appending the index to it:

key={`${opt.value}-${i}`}

which should always be unique since the index is used but there is another part of the code for hidden inputs

 renderHiddenInput = () => {
    debug('renderHiddenInput()')
    const { value } = this.state
    const { multiple, name, options, selection } = this.props
    debug(`name:      ${name}`)
    debug(`selection: ${selection}`)
    debug(`value:     ${value}`)
    if (!selection) return null

    // a dropdown without an active item will have an empty string value
    return (
      <select type='hidden' aria-hidden='true' name={name} value={value} multiple={multiple}>
        <option value='' />
        {_.map(options, option => (
          <option key={option.value} value={option.value}>{option.text}</option>
        ))}
      </select>
    )
  }

in this one the key is set to only the value, not the value plus index.

 <option key={option.value} value={option.value}>{option.text}</option>

this might be your problem, if you have duplicate values then the key will not be unique. Double check the options list to make sure you don't have duplicate values.

Sign up to request clarification or add additional context in comments.

3 Comments

Hey, thanks for info. I understand now. I think the issue happens because some of data is cached. Basically I am making auto-complete search and in jQuery version of Semantic UI I would make saveRemoteData to be equal false to prevent it. However in React version that setting is not present (or at least as far as I know-- github.com/Semantic-Org/Semantic-UI-React/issues/1124)
If your not familiar already, I highly suggest using the Chrome React Tools. This will let you look your options collection and double check the values.
Hey thanks for advice, I am using Firefox version of React tools. I did a bit more digging and found the duplicates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.