Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dropdown: option keys fallback to values incorrectly #1720

Closed
notgiorgi opened this issue May 31, 2017 · 7 comments
Closed

Dropdown: option keys fallback to values incorrectly #1720

notgiorgi opened this issue May 31, 2017 · 7 comments
Labels

Comments

@notgiorgi
Copy link

Steps

if we define our Dropdown component like this:

const opts = [
  {
    key: 0,
    value: 1,
    text: 'Foo',
  },
  {
    key: 1,
    value: 2,
    text: 'Bar',
  },
]

const MyDropdown = () => <Dropdown selection options={opts} />

Note: this only happens with selection prop true, because only in that case, select is rendered behind the scenes

Expected Result

This should render <select> with two <option>s with keys 0 and 1

Actual Result

image

This tries to render <select> with two <option>s with keys 1 and 1 because of { option.key || option.value } (see this line of the code https://github.com/Semantic-Org/Semantic-UI-React/blob/master/src/modules/Dropdown/Dropdown.js#L1074)

I think this line should be rewritten to only fallback to option.value when option.key is either undefined or empty string. All other falsy values are valid keys, react converts them to strings.

Version

last

Testcase

https://codepen.io/notgiorgi/pen/ZKgBob?editors=0010 (you cannot use devtools on codepen)

@notgiorgi
Copy link
Author

notgiorgi commented May 31, 2017

One approach can be to write a helper function:

function getValidKey(key) {
  switch (key) {
    case null: return 'null'
    case false: return 'false'
    case 0: return '0'

    case undefined:
    case '':
      return false
    default: return key
  }
}

and then

key={getValidKey(option.key) || option.value}

Or we could do

function getValidKey(key, fallback) {
  switch (key) {
    case undefined:
    case '':
      return fallback
    default: return key
  }
}

and then

key={getValidKey(option.key, option.value)}

I can send a PR

@layershifter
Copy link
Member

@notgiorgi Nice catch, there is also #1710. I think that both issues should be fixed in a single PR.

@notgiorgi
Copy link
Author

notgiorgi commented May 31, 2017

I can do them both, which solution should I go with? I mentioned two above.

@layershifter
Copy link
Member

layershifter commented May 31, 2017

I don't like idea with getValidKey because key handling is responsibility of our factories. However, it means a large refactoring like #1619, not time for this.

getValidKey

I think it will be enought to use lodash's isNil (check to null and undefined):

const getKeyOrVal = (key, value) => _.isNil(key) ? value : key

And it should be placed directly in Dropdown.js because as I said this pattern shouldn't reused in other components.

These lines should be updated:

update factory's usage

This will fix #1710. I commented why this problem occurs, fix for it is pretty simple:

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

@notgiorgi I'll be glad to see PR that makes these changes.

@notgiorgi
Copy link
Author

I was gonna say, I'll get into it on weekend, but it seems to be done already 😄

@levithomason
Copy link
Member

Yes sir, cutting a release as we speak.

@levithomason
Copy link
Member

Released in semantic-ui-react@0.68.5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants