React-bootstrap-typeahead: Menu rendering should be delayed until new options arrive

Created on 19 Oct 2017  路  10Comments  路  Source: ericgio/react-bootstrap-typeahead

Version

1.4.2

Steps to reproduce

Create an <AsyncTypeahead> with minLength=3. After the user types in the third character, a search is executed and the results are shown, just as expected.

The user then deletes all characters and starts typing again, with another search query term. After the third keystroke, a new search is being executed, but in the meantime the dropdown menu shows up, showing the results of the first query. Once the results of the second query come in, the drop down menu is re-rendered. This leads to user confusion and interface flickering.

(The problem is independent of minLength, but is more prominent when using it.)

Expected Behavior

Async Typeahead should wait after a query is being executed until new (changed) options arrive.

async bug

Most helpful comment

This is happening because of the debouncing that's built into the async version. There's a delay between the time the user has finished typing and when the onSearch callback fires, during which other things might happen immediately. This is admittedly weird, so I'll have to think about what the right behavior is and how it might be fixed (eg: temporarily suppressing the menu).

All 10 comments

Can you post an example of your code as well as the 2 queries you're making? I don't repro this issue in the example, so my guess is that you're passing the original results into the component when you shouldn't be.

Nevermind, I was able to repro the issue. Thanks.

I think this happens regardless of the minLength prop. This happens when you start typing and delete and start again and then No matches found. is shown.

Yeah, I stated that. But I felt it to be more prominent if you set minLength because it is quite obvious that an old search results show up then. If minLength is 0, it only appears as a restoration of the last state before you closed the menu.

@derwaldgeist My bad, I missed that last bit.

This is happening because of the debouncing that's built into the async version. There's a delay between the time the user has finished typing and when the onSearch callback fires, during which other things might happen immediately. This is admittedly weird, so I'll have to think about what the right behavior is and how it might be fixed (eg: temporarily suppressing the menu).

Thanks for sharing your insights!

The only way I can get this issue to reproduce is if the second search string is a substring of the first (eg: first search: 'ericgio', second search: 'gio'). Otherwise it seems to behave as one would expect.

Digging into this some more, I'm not convinced it's truly a bug. The reason it's happening (at least in the case of the public examples) is that the parent component calling AsyncTypeahead always passes the latest set of results into the typeahead. So after an initial set of results is fetched, subsequent user queries will initially just filter the existing results until a new result set is returned.

To avoid this behavior, the right thing to do is treat the component in a controlled way and clear the options when the input changes:

<AsyncTypeahead
  onInputChange={(text) => {
    if (this.state.options.length) {
      this.setState({options: []});
    }
  }}
  ...
/>

Another way to solve avoid this is to disable client-side filtering for the async component. I think this is probably fine in most cases, since the filtering isn't really needed. Not sure if there are some less common cases I might not be thinking about, though.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lehresman picture lehresman  路  8Comments

jtmunn picture jtmunn  路  4Comments

yedyharova picture yedyharova  路  9Comments

hslojewski picture hslojewski  路  3Comments

mflauer picture mflauer  路  4Comments