React-select: [v2] Loading indicator disappears once the menu is opened

Created on 12 Sep 2018  路  11Comments  路  Source: JedWatson/react-select

If we open the menu while Async component is loading the options, loadingIndicator disappears even though loadOptions is not yet completed. noOptionsMessage displayed until the options are loaded but no more loadingIndicator(Even if you open/close the menu, it's same). There is no indication if the options are still loading.

Although it's a simple scenario, I couldn't find a similar bug report. Simple test case forked from the web site: https://codesandbox.io/s/14919k7q4

Would there be an alternative way to fix this problem?

issubug-confirmed

Most helpful comment

@Atralbus So the problem is here: https://github.com/JedWatson/react-select/blob/master/src/Async.js#L108

It looks like when you click away from the dropdown, it triggers an onInputChange and since inputValue is "", it sets the isLoading state to false.

I think this is definitely a bug, @jossmac, can you please confirm this?

All 11 comments

@Atralbus I tried it out and I wasn't able to reproduce this issue. What OS and browser are you using?

@sahibjotsaggu I thought it's a common problem so I didn't mention OS and browser in the issue. But here's the original spec that I run into the problem.
macOS Sierra, Chrome - 68.0.3440.106

Now, I tried it with Windows 10, Firefox 63.0b4. It's same.

@Atralbus Okay! I didn't see that you mentioned the opening and closing of the menu. Looks like it does disappear. I am looking into it right now.

@sahibjotsaggu Sorry about that, I should change my statement to once the menu is opened and closed. :)

@Atralbus So the problem is here: https://github.com/JedWatson/react-select/blob/master/src/Async.js#L108

It looks like when you click away from the dropdown, it triggers an onInputChange and since inputValue is "", it sets the isLoading state to false.

I think this is definitely a bug, @jossmac, can you please confirm this?

@sahibjotsaggu thanks for looking into this. I didn't have anything to do with the async implementation though I'm afraid, that was @JedWatson and @gwyneplaine I think.

Ran into the same issue. @Atralbus did you end up finding a workaround?

@matthova I think the best option is to handle loading indicator manually with isLoading prop. And I'm using Select component instead of Async since the loadOptions is causing different problems. I reload options when it's necessary.

Sample code with RxJS to show how I handle loading in the state;

export default class CompWithSelect extends Component {
  constructor(props: Props) {
    super(props)
    this.state = {
        options: [],
        input: '',
        loading: false
    }
    this.search$ = new Subject()
  }

  componentDidMount() {
    this.search$
    .debounceTime(500)
    .do(() => this.setState({ options: [], loading: true }))
    .switchMap(str => this.props.dispatch(runSimpleProgram(str))
      .scan((acc, curr) => curr.name === 'TaskResult' ? [...acc, ...curr.data] : acc, [])
      .finally(() => this.setState({ loading: false }))
    )
    .subscribe(
      (data) => this.setState({
        options: data.map(({value}) => ({value, label: value}))
      }),
      () => this.setState({ loading: false })
    )
  }

  componentDidUpdate(prevProps: Props) {
    if (/* related props changed */) {
      this.search$.next(this.state.input)
    }
  }

  componentWillUnmount() {
    this.search$.unsubscribe()
  }

  handleInputChange = (input: string) => {
    if (this.state.input !== input) {
      this.setState({input})
      this.search$.next(input)
    }
  }

  handleValuesChange = (options: Array<{value: string}>): void => {
    const values = options
      .map(prop('value'))

    this.props.onValuesChange(values)
  }

  handleFocus = () =>
    isEmpty(this.state.options)
    && this.search$.next(this.state.input)

  render () {
    const { values } = this.props
    const { options, loading } = this.state
    return (
      <div>
        <Creatable
          name='values'
          isMulti
          isLoading={loading}
          value={values.map(v => ({label: v, value: v}))}
          options={options}
          filterOption={() => true} // to prevent react-select filter
          onInputChange={this.handleInputChange}
          onChange={this.handleValuesChange}
          onFocus={this.handleFocus}
          closeMenuOnSelect={false}
          createOptionPosition='first'
          allowCreateWhileLoading
        />
      </div>
    )
  }
}

@Atralbus as you mentioned that

I think the best option is to handle loading indicator manually with isLoading prop.

This issue can be linked to an already existing issue #2986 and can be resolved with the following fix #3319

Isn't this a real bug.. i'm facing this still..
The real behavior should be if defaultOptions is true, then when we open and close the select it should not trigger loadOptions('') and set isLoading to false.. instead it should just ignore..

Hello -

In an effort to sustain the react-select project going forward, we're closing old issues.

We understand this might be inconvenient but in the best interest of supporting the broader community we have to direct our efforts towards the current major version.

If you aren't using the latest version of react-select please consider upgrading to see if it resolves any issues you're having.

However, if you feel this issue is still relevant and you'd like us to review it - please leave a comment and we'll do our best to get back to you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mbonaci picture mbonaci  路  3Comments

sampatbadhe picture sampatbadhe  路  3Comments

batusai513 picture batusai513  路  3Comments

juliensnz picture juliensnz  路  3Comments

x-yuri picture x-yuri  路  3Comments