JedWatson / react-select

The Select Component for React.js
https://react-select.com/
MIT License
27.55k stars 4.12k forks source link

Promise error with loadOptions #1718

Closed matthewboman closed 4 years ago

matthewboman commented 7 years ago

Previously, I was using a callback for asynchronously loading options from an API call:

const loadOptions = (input, tripId, destinationIndex, cb) => {
  if (!input) {
    cb(null, { options: [] })
    return
  }

  TVApi.spot.autocomplete(input, tripId, destinationIndex)
    .then((spots) => {
      const newOptions = spots.map(spotToOption).slice(0, 4)
      cb(null, { options: newOptions })
    })
    .catch(() => cb(null, { options: [] }))
}

but switched over to using promises:

const loadOptions = (tripId, destinationIndex, input) => {
  if (!input) {
   return Promise.resolve({ options: [] });
  }
  function getMusement(input) {
    return TVApi.musement.autocomplete(input)
      .then((m) => {
        const musementOptions = m.map(musementToOption).slice(0, 3)
        return musementOptions
      })
  }
  function getFourSquare(tripId, destinationIndex, input) {
    return TVApi.spot.autocomplete(tripId, destinationIndex, input)
      .then((fs) => {
        const fsOptions = fs.map(fsToOption).slice(0, 2)
        return fsOptions
      })
  }
  return Promise.all([getMusement(input), getFourSquare(tripId, destinationIndex, input)])
    .then((allData) => {
      const merged = [].concat.apply([], allData)
      return {options: merged}
    })
}

The problem is, with the if statement in the promise-based verison, the select-bar stops responding. It worked before when using callbacks. Also, the promise-based version works fine without the if statement.

Is there a way to get the if statement working with promises, or is it not necessary to return an empty array when blank?

agirton commented 7 years ago

Hi @crashspringfield which version are you using?

the select-bar stops responding.

Do you mean that you can't enter any values? Can you clarify this a bit more?

matthewboman commented 7 years ago

I could enter values, but the select-bar would no longer populate with values from the API calls in the returned promise.

I also tried turning the if-statement into a promise:

if (!input) {
   return Promise.resolve({ options: [] });
}

but that didn't work either.

agirton commented 7 years ago

Hmm this should work just fine if you're using the latest version. Especially because this works here https://github.com/JedWatson/react-select/blob/master/examples/src/components/GithubUsers.js#L36. Do you have a bit more code I can take a look at? Maybe the props you're setting?

matthewboman commented 7 years ago

Here's the component:

      <Select.Async
        name="addactivitysearch-field"
        className="addactivitysearch-wrapper"
        placeholder="Venue name ..."
        value={this.state.query}
        arrowRenderer={() => ''}
        filterOptions={filterOptions}
        clearable={false}
        autoload={false}
        cache={false}
        onBlurResetsInput={false}
        optionRenderer={renderOption}
        loadOptions={(input) => loadOptions(input, this.props.tripId, this.props.destinationIndex)}
        autoBlur
        onInputChange={inputValue => this.setState({ inputValue })}
        onChange={(query) => {
          this.props.openActivityDetailModal(query.data || {}, false, query.data ? query.data.id : null)
          if (query.type && query.type === 'more') {
            this.setState({ query: undefined })
            return
          }
          this.setState({ query })
        }}
        onFocus={() => this.state.query ? this.setState({ query: undefined }) : undefined}
        menuRenderer={menuRenderer}
      />

I switched the order of the props so the function is now:

const loadOptions = (input, tripId, destinationIndex) => { ... }

and the order of props being passed in is also changed for the API calls.

tripId and destinationIndex are just static numbers passed down from the container component. For example, I'm running a test where tripId = 5464' anddestinationIndex=0`

dmamills commented 7 years ago

I'm having a similar issue using Select.Async, I can see the values from my promise resolving { options: [ {...} ] actually held in the state of the component, but it's not rendering all them.

sabarasaba commented 7 years ago

@dmamills Im facing the same issue, where you able to fix it?

coderberry commented 7 years ago

+1

p10ns11y commented 7 years ago

+1

ntomkevich commented 5 years ago

Hey guys has this ever been resolved?? resolved by fixing my filterOption function.

bladey commented 4 years ago

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!