Reputation: 195
I am developing a user search feature in my react/redux application using react-bootstrap-typehead: http://ericgio.github.io/react-bootstrap-typeahead/
The user search calls an API to search the list of users, so I am using the AsyncTypeahead component.
Since I are using Redux, I am storing the loading and search results within the store, so my code looks something like this:
const { searchPeople, loading, searchResults, selectedPerson } = this.props;
<AsyncTypeahead
isLoading={loading}
options={searchResults}
labelKey="DisplayName"
clearButton
minLength={5}
onSearch={searchPeople}
onChange={handleChange}
placeholder="Search for a user..."
renderMenuItemChildren={option => (
<TypeaheadItem key={option.EmployeeID} item={option} {...this.props} />
)}
/>
The onSearch={searchPeople}
calls an action in Redux to call the API and store the results in "searchResults":
const searchPeople = term => async dispatch => {
dispatch({
type: REQUEST_SENT
});
const results = await dispatch(applicationActions.peopleSearch(term));
dispatch({
type: REQUEST_RECEIVED,
data: results
});
};
My "peopleSearch" function is stored in another action where I have all of our user search functionality. That is why I am dispatching to another action.
const peopleSearch = searchTerm => async () => {
const url = `https://api-personSearch.test.com/search=${searchTerm}&Output=JSONP`;
const response = await fetchJsonp(url);
const data = await response.json();
return data.slice(0, 10);
};
Everything works perfectly if I search for a user typing slowly. The problem is, if I type a users name quickly or at a normal pace, multiple "REQUEST_SENT" dispatches get called before any "REQUEST_RECEIVED" get called. So looking at the Redux Dev Tools shows results looking like this:
REQUEST_SENT
REQUEST_SENT
REQUEST_SENT
REQUEST_RECEIVED
REQUEST_RECEIVED
REQUEST_RECEIVED
What ends up getting sent to the interface does not end up being the results for the last letter the user ended up typing.
What would be the proper way to use AsyncTypeahead with Redux so that the results are returned in the proper order that they are sent?
One thing that ended up working (even though I think it's sort of a hack) is adding a "delay" to the AsyncTypehead. Adding a delay={1000}
prop to the AsyncTypeahead component gives the api just enough time to finish it's call before another call to the api is made.
I would like to find a better solution if one is possible.
Upvotes: 5
Views: 2212
Reputation: 528
I think it's a bug in the component where AsyncContainer
and TypeheadContainer
get out of sync. The delay approach works most of the time but even then I could type it in a way that I would get no results. Not happy with this answer either but turning off the cache is the only way to guarantee that doesn't happen.
useCache={false}
Upvotes: 0
Reputation: 36542
I'm having a different issue in my usage, but I can suggest a solution to the ordering problem.
Ideally, you'd cancel the previous request when receiving a new one in onSearch()
, but this will have the same effect. If the user keeps typing, delaying long enough for onSearch()
to be fired but quick enough to cause overlapping requests, only the last request will display results.
Upvotes: 1