React-select: [Question] - Is it possible to just pass a id to value rather than label and id ?

Created on 10 Aug 2018  路  16Comments  路  Source: JedWatson/react-select

I would expect this to work like this:

<select value={this.state.valueId} onChange={this.handleChange}>
     <option value="some_id_name">Grapefruit</option>
</select>

where as im finding it needs to be passed in value={{label: this.state.label, value: this.state.valueId}}
This is highly annoying as all my results come from a database of just IDs and i use a reference list of options to select them

Any work arounds ?

im currently having to search for the correct label against my reference data which is more loops than id rather be doing.

Thanks
Luke

categordocumentation categorquestion

Most helpful comment

I totally agree with @designalchemy

Version 1.x had the correct implementation. The value attribute in select options are always unique. Why do we have to provide an object for the value prop 馃槙

It means that I have to do a filter operation like Luke has mentioned above or custom workarounds for Select inputs to place nice with my other form components. This adds unnecessary complexity.

Why was this change made?

All 16 comments

I totally agree with @designalchemy

Version 1.x had the correct implementation. The value attribute in select options are always unique. Why do we have to provide an object for the value prop 馃槙

It means that I have to do a filter operation like Luke has mentioned above or custom workarounds for Select inputs to place nice with my other form components. This adds unnecessary complexity.

Why was this change made?

馃憢 I don't know how this thread will go, but in the meantime here is how I tackled the issue to avoid surfacing this breaking change to my components using <Select>:

  • pass a value literal in defaultValue prop
  • have the defaultValue prop find the associated label using the literal
  • wrap react-select in my own component to take care of the above
import ReactSelect from "react-select";

function Select({ defaultValue, options, ...otherProps }) {
  return (
    <ReactSelect
      defaultValue={
        defaultValue && {
          value: defaultValue,
          label: options.find(o => o.value === defaultValue).label,
        }
      }
      options={options}
      {...otherProps}
    />
  );
}

And use it like so:

<Select
  options={[
    { id: "Y", label: "Yellow" },
    { id: "G", label: "Green" },
    { id: "B", label: "Blue" },
  ]}
  defaultValue="G"
/>;

This is using defaultValue on purpose : I rely on react-select's internal state to handle the changes after mounting.

Also, @jossmac is commenting this in https://github.com/JedWatson/react-select/pull/2908#issuecomment-413102198

The decision to limit value to an option object makes many things easier for maintainers and consumers. Unfortunately, just not this one case.
I'd like some more input on this, but I think it's not too much to ask consumers to write a helper function to derive the option object from a given key:

@designalchemy @gtaylor44

I understand your frustration at this change to the API, I'll try to provide some context. Having the value as a literal representation of option(s) provided makes it easier to perform complex operations, both for maintainers and consumers.

It means that I have to do a filter operation like Luke has mentioned above or custom workarounds for Select inputs to place nice with my other form components. This adds unnecessary complexity.

The added complexity to react-select, if we were to introduce this change, is an order of magnitude greater than a one-liner in consumer code. For instance:

const valueFromId = (opts, id) => opts.find(o => o.value === id);

<Select value={valueFromId(this.props.options, this.props.id) />

I don't really see this as a "workaround", it's just the API. This component was created because the native select doesn't meet the needs of modern web applications; the API is more sophisticated because it needs to be.

@jossmac

Thanks for the reply,

Fair enough if its going to say like this for good reason, i guess my programming background says "avoid all the loops possible" but the expense of a simple find is minimal.

Just out of curiosity what was the problem with just passing the ID ? i.e what does it fix / make easier passing it the whole label ?

Thanks
Luke

@jossmac , @designalchemy

I too end up wrapping this component in another wrapper to be able to pass a value, values are what we have stored in a database not the object.

The beauty of react is that we can make a component that handles is own options, so we can reuse it. Now I need to externalize the options to be able to set the value, and wrap it in a component with its own state.

Why not make it so that passing as value

{ value : "myKey" }

will work too to set the value, instead only allowing

{ value : "myKey" , label : "Whatever" }

Label can be anything in a multi-language environment and is not tied to value.

I can think of more use cases where where value needs to stay the same but label can change.

And yes, I would not mind the onChange event to fire when setting value like this to know the label too in my state, I acknowledging that this makes it difficult conceptually....

Like this we can have the best of two worlds?

Totally understand the decision to go in this direction, and it's not too tough to refactor my old components to work with the new API, but this should probably be called out more clearly in both the intro documentation as well as the upgrade documentation. It might also be nice to use a different prop name than value in order to make it clear that this component isn't a drop-in replacement for a normal select.

I can take a stab at writing a bit of documentation if that would be welcome.

@SeanRoberts thank you for your offer to update the documentation, that would be very welcome.

馃挬, I just spent 2-3 hours tying to figure out why I couldn't get the select to render with the selected value. 馃 馃槩

This is why!

@jossmac I am having issues getting the label when I have grouped options :(

@aanchalgera yeah, you'll need a recursive function to resolve nested options. One of many reasons simple value is more hassle than it's worth

This keeps coming up. Part of the problem is documentation, for sure, but if you still really want to use simple value I've created a wrapper. You can get it from npm or take a look at the source and grab whatever you want.

Usage

<SimpleValue options={[...]} value="blue">
  {props => <Select {...props} />}
</SimpleValue>

Supports

  • simple value
  • simple defaultValue
  • grouped options
  • custom getOptionValue
  • isMulti where value/defaultValue is a comma delimited string

@jossmac

Also, @jossmac is commenting this in #2908 (comment)

The decision to limit value to an option object makes many things easier for maintainers and consumers. Unfortunately, just not this one case.
I'd like some more input on this, but I think it's not too much to ask consumers to write a helper function to derive the option object from a given key:

What are the many things made easier for example?

So all of these secondary features are now slightly "easier" at the expense of making the primary use-case much, much more complex for everybody. That's a terrible decision.

Also, I don't see how it handles large lists faster because the calling code still has to filter to find the correct option to pass to the value prop, something the component should just be doing internally anyway.

Surly the idea of a helper library such as this is not to make it easier for the Devs but easier for the user ? This seems like lazy devving

So all of these secondary features are now slightly "easier" at the expense of making the primary use-case much, much more complex for everybody. That's a terrible decision.

Wow, this is harsh. React-select is open-source software: it's your choice to use it. If you don't like it, then use something else.

I don't want to be mean or aggressive here...but I'd like to show support to @jossmac. He listened to the community and provided a helper that will allow the old behavior. Kudos to him!

I don't want to get into a fight or sterile debate here. I won't answer any response to my post (if any). So again : just wanted to show support to @jossmac (and all the committers) 鉂わ笍

I think we could take some time to think about the effort and commitment it takes to massively contribute to a 14K+ 猸愶笍 repository...

Was this page helpful?
0 / 5 - 0 ratings