React-select: Don't clear input value after receiving new options

Created on 8 Oct 2015  路  13Comments  路  Source: JedWatson/react-select

We are using redux in our app. And we load options for autocomplete by just invoking async action on onInputChange event. But when Select receives new options array from the app state, it rerenders itself and clears input value. Is there anything we can do about it?

Most helpful comment

I also run into this issue. But i found much more better workaround. When you mapping your search result from the server use something like:

options.map((option) => {
    return {
        label: option.title,
        value: {
            id: option.id,
            title: option.title,
        }
    };
}),

And then use valueRenderer options in order to make react-select able to render your complex object values

function valueRenderer(value, index) {
  return value.title;
}

I guess the problem is that react-select stores only selected IDs and when new options are comming without our old selection, react-select can't find corresponding label and there is no data where it can find this label. By using custom values, that contains label data and by using valueRenderer we solve this issue.

All 13 comments

i'd be curious to know about this too

+1

+1

Here is an example that reproduces the problem:

import React from 'react';
import Select from 'react-select';

var ReloadOptions = React.createClass({
  displayName: 'ReloadOptions',

  getInitialState () {
    return {
      isLoading: false,
      options: [],
      text: ""
    };
  },

  onInputChange (text) {
    this.setState({isLoading: true, options: [], text: text})
    setTimeout(this.receivedOptions, 2000)
  },

  receivedOptions () {
    let d = new Date();
    var options = [{value: d, label: d.toString()}];
    this.setState({isLoading: false, options: options})
  },

  render () {
    return (
      <div className="section">
        <Select
          isLoading={this.state.isLoading}
          value={this.state.text}
          options={this.state.options}
          onInputChange={this.onInputChange}
          />
      </div>
    );
  }
});

module.exports = ReloadOptions;

Setting a filterOptions which just returns options || [] (and asyncOptions) seems to workaround it:

import React from 'react';
import Select from 'react-select';

var ReloadOptions = React.createClass({
  displayName: 'ReloadOptions',

  getInitialState () {
    return {
      text: ""
    };
  },

  loadOptions (input, callback) {
    this.state.callback = callback
    setTimeout(this.receivedOptions, 2000)
  },

  filterOptions (options, filter, values) {
    if (!options) options = []
    return options
  },

  receivedOptions () {
    let d1 = new Date().getTime() + "-1"
    let d2 = new Date().getTime() + "-2"
    let options = [
      {value: d1, label: d1},
      {value: d2, label: d2}
    ];
    this.state.callback(null, {options: options, complete: false})
  },

  render () {
    return (
      <div className="section">
        <Select
          value={this.state.text}
          filterOptions={this.filterOptions}
          asyncOptions={this.loadOptions}
          cacheAsyncResults={false}
          autoload={false}
          />
      </div>
    );
  }
});

module.exports = ReloadOptions;

I had this problem using a synchronous, multi-select implementation, so the above didn't fix it for me.

I put my Select element in a small decorator component that checks the length of the tags prop each update. Now the Select doesn't update for every single state change of the component it's included in, so my input field doesn't get wiped out unless tags are modified:

React = require 'react'
Select = require 'react-select'

module.exports = React.createClass

  getDefaultProps: ->

    tags: []
    onChange: ->

  shouldComponentUpdate: (nextProps, nextState) ->

    nextProps.tags.length isnt @props.tags.length

  render: ->

    <Select
      multi={ true }
      allowCreate={ true }
      value={ @props.tags }
      onChange={ @props.onChange }
      onInputChange={ @_onInputChange } />

Still getting the issue with redux 3 and react 0.14, value is empty string on redux-form/BLUR, any idea?

@jonathanasquier any luck?

Yes, sorry, I answered in another thread :
"I'm using redux-form and the onBlur event used to dispatch empty values which is quite ennoying.
I'ts ugly but it works (1.0.0-beta6):"

<Select
     options={options}
    {...field}
     onBlur={function(){}}
 />

That will do for now...

I ran into this issue recently. Seems to be down to https://github.com/JedWatson/react-select/blob/master/src/Select.js#L982

That call builds up a values array by filtering the values passed against the options. This breaks a use case like ours, which is essentially a keyword search (user can type in anything, options will change on each input change, selected options need to stay put).

Workaround for me was to ensure that the currently selected value(s) always appeared in the options prop passed to the component.

I also run into this issue. But i found much more better workaround. When you mapping your search result from the server use something like:

options.map((option) => {
    return {
        label: option.title,
        value: {
            id: option.id,
            title: option.title,
        }
    };
}),

And then use valueRenderer options in order to make react-select able to render your complex object values

function valueRenderer(value, index) {
  return value.title;
}

I guess the problem is that react-select stores only selected IDs and when new options are comming without our old selection, react-select can't find corresponding label and there is no data where it can find this label. By using custom values, that contains label data and by using valueRenderer we solve this issue.

I'm still having this issue when after async loading the options and selecting one the value selected does not get displayed due to a redux re-render. I tried the workarrounds here and could not manage to make it work.

My guess is that when the prop value gets updated from redux the options are not there anymore. But even If I add a custom filter and add the value as the only option the value selected does not appear on the input.... :(

Could someone post an example please, my <Select.Asyc value{FROM_REDUX_CHANGE}... is the probably whats causing the issue.

Version 1 of react-select is no longer supported.

In the best interest of the community we've decided to spend the time we have available on the latest version.

We apologise for any inconvenience.

Please see:

  1. v1 to v2 upgrade guide
  2. v1 documentation and examples
Was this page helpful?
0 / 5 - 0 ratings

Related issues

MalcolmDwyer picture MalcolmDwyer  路  3Comments

sampatbadhe picture sampatbadhe  路  3Comments

ericj17 picture ericj17  路  3Comments

pashap picture pashap  路  3Comments

steida picture steida  路  3Comments