React-select: Help debugging options that aren't displayed

Created on 28 May 2019  路  4Comments  路  Source: JedWatson/react-select

My app responds to each keystroke, retrieves a new list of matches, and sets options. Pretty standard stuff. I had similar code and use in a different app and that worked perfectly fine. In the new app, however, the menu is populated sometimes, but nothing shows up for most inputs. I set breakpoints and dumped options to console to verify that my backend is reliably returning the results and that I'm setting the options member correctly as shown below:

            this.setState({options: goptions}, () => {
                console.log(this.state.options);
            });

My control is setup as shown at the end. In this example, the results are grouped, but I have had the same problem with non-grouped display. I was initially working with version 2.x and just now upgraded to version 3. No change in behavior at all.

I tried setting breakpoints in react-select's code, but being not too familiar with debugging react components, not clear where to set breakpoints and what to look for.

I set exception handlers in my code, but no exceptions caught. I traced different states (e.g. ismenuclosed) and all of them look fine. So not clear why react-select is not updating the dropdown menu most of the time. I looked at the options values that are being rejected and those that are successfully displayed and I can't see any obvious differences between the two lists. Sometimes the first two keystrokes, e.g. "ed", results in a display as expected, but the third keystroke resulting in "edw", which has results, results in an empty menu.

I tried with Firefox and Chrome and same behavior on both.

Appreciate help pointing to things I may be missing or tips on how to debug this. I just setup the react debugger too.

        return <WikiCompletionSelect
                isClearable={true}
                id="wikicompletion"
                inputValue={this.state.inputValue}
                components={{Option, LoadingMessage, NoOptionsMessage}}
                onChange={this.onSelectionChanged.bind(this)}
                onInputChange={this.handleInputChange.bind(this)}
                placeholder={'Start typing'}
                blurInputOnSelect={false}
                openMenuOnClick={true}
                openMenuOnFocus={true}
                maxMenuHeight={this.props.isMobile ? 250 : 600}
                theme={customTheme}
                options={this.state.options}
                onMenuClose={this.handleMenuClose.bind(this)}
                onFocus={this.handleFocus.bind(this)}
                onBlur={this.handleBlur.bind(this)}
                formatGroupLabel={formatGroupLabel}
            />

Most helpful comment

Found the problem. It was the default filter implementation of react-select. I don't need that functionality at all, so ended up writing a pass through custom filter. Problem solved. Wish I was aware of the way the default filter worked. This wasn't a problem in my previous app due to the nature of the data.

All 4 comments

I made some progress but still stuck. The core of the problem is some input patterns (always the same ones) end up displaying results while others (lot higher percentage of these) end up displaying nothing. I updated my options setting code to always set the same hardcoded options values. Then I set breakpoint in the buildMenuOptions function. In both cases (success and failure of display), the reduce function has the same value for item.options, but in the success case, the subsequent items.map yields valid children and in the failure case, it yields nothing. I have no idea why it is behaving this way -- as mentioned above, the input options are the same hardcoded values for both cases and the only difference would be in the typed input (e.g. "a" fails but "e" and "ed" work).

What else can I do to find my problem?

value: function buildMenuOptions(props, selectValue) {

      return options.reduce(function (acc, item, itemIndex) {
        if (item.options) {
          // TODO needs a tidier implementation
          if (!_this3.hasGroups) _this3.hasGroups = true;
          **var items = item.options;**
          var children = items.map(function (child, i) {
            var option = toOption(child, "".concat(itemIndex, "-").concat(i));
            if (option) acc.focusable.push(child);
            return option;
          }).filter(Boolean);

          if (children.length) {
            var groupId = "".concat(_this3.getElementId('group'), "-").concat(itemIndex);
            acc.render.push({
              type: 'group',
              key: groupId,
              data: item,
              options: children
            });
          }

Found the problem. It was the default filter implementation of react-select. I don't need that functionality at all, so ended up writing a pass through custom filter. Problem solved. Wish I was aware of the way the default filter worked. This wasn't a problem in my previous app due to the nature of the data.

Wow, I just came across this issue and it was doing my head in too. In hindsight, it's kind of obvious, but because everything works seamlessly it's confusing when it stops working. The full explanation can be found here https://github.com/JedWatson/react-select/issues/2865#issuecomment-508407878

Basically this happens when you have a select that does async calls on select input & you get back results which pass onto your select options. However what you input is also being use for filtering the options by react-select via the label key; so if you get back 5 results but the labels of those don't match what you have input into react-select, 0 will show up.

If you inspect your select component, you'll see the options props with your data, but in the state, the menuOptions.render shows empty array.

@bot19 and @theconnectionist -- THIS SOLVED MY PROBLEM. I rewrote my components a few times thinking the way I was updating and passing options to the select were somehow conflicting. This was a damn nightmare trying to figure out-thank you for posting your findings! I easily was 5 hours into this and this was it!

Backend: Performs a fuzzy search so if I search "Jon", the results found that match are "Bon". But because the frontend didn't recognize Jon as a match for Bon, it was always filtering the options out! SIGHHHHH

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mjuopperi picture mjuopperi  路  3Comments

ericj17 picture ericj17  路  3Comments

juliensnz picture juliensnz  路  3Comments

MindRave picture MindRave  路  3Comments

MalcolmDwyer picture MalcolmDwyer  路  3Comments