sickdyd / react-search-autocomplete

A search box that filters the provided array of objects
https://sickdyd.github.io/react-search-autocomplete
MIT License
220 stars 84 forks source link

API call after onSearch #10

Closed amaioru0 closed 2 years ago

amaioru0 commented 3 years ago

Hi there,

Thank you for this amazing component!

In my handleOnSearch function I make an API request to get results based on the user input. However, the results that are shown are from the previous API call so I am wondering if there is a way to first make the API call and then show the results only after I updated the data.

Something like beforeSearch would be amazing 🥇

Thanks

sickdyd commented 3 years ago

Hello @amaioru0,

I updated the package to version 5.0.3, now if the items change, the results will be updated as well. I built a little demo in codesandbox: https://codesandbox.io/s/nifty-frost-7gurg?file=/src/App.js

I added a fake fetch request onSearch that takes 1 second to complete (to mock an API request). Once the request has completed, you will see the updated search results in the list.

demo1

To verify how it works, try to type a number, you'll see that after 1 second the values are updated. You can do this multiple times.

The issue here is that for a brief time users will see the "old" results. I am thinking to add a "loading" prop to force the component to display a loader rather than results if your fetch request has not yet completed. What do you think?

Thanks for reporting the issue.

amaioru0 commented 3 years ago

Hi @sickdyd,

Thank you so much for resolving this issue. It's working perfect now!

Regarding the loading state, I think it would be cool to have a loading indicator at the end of the input in the right side. A little circle that indicates the loading state but still display old results while loading and the ability to pass in a custom component for the loader that is displayed in the right side of the input.

Thank you again for resolving this issue!

EDIT: Another little issue which I am not sure if it is from the component, is that when I type in something, sometimes not all the keys that I type are getting typed. For example, if I type in Dublin sometimes I end up with Dubln so the i gets skipped.

sickdyd commented 3 years ago

Hello @amaioru0,

The idea of the loader seems nice! I'll try to implement it as soon as I have the chance.

I noticed now that my fix introduces the issue you are talking about while typing. I will try to sort it out ASAP.

Thanks for letting me know!

sickdyd commented 3 years ago

Hello @amaioru0,

One quick fix is to set inputDebounce to 500. This solved the issue in my codesandbox demo at least. Maybe you can try to play around with this prop and see if it helps, in the meantime I'm trying to figure out a better fix.

amaioru0 commented 3 years ago

Hi @sickdyd,

Thanks for your reply.

inputDebounce 500 seems to make it work a bit better but the issue is still present.

Thank you again for all of this!

amaioru0 commented 3 years ago

Hi @sickdyd,

I am wondering, would it be possible to add something like onMouseOverItem that would allow me to know which item the user is hovering.

Also would it be possible to have the option for the input value to have a default text value, pass a object item that contains name which would be used as the default text value for the input?

It would allow me to do some really cool stuff in my app search component that I am building.

sickdyd commented 3 years ago

Hello @amaioru0!

Sorry for the long wait. I deployed the version 5.0.8 today, and this will fix the issue you were noticing while typing. You can see a working example in this codesandbox: https://codesandbox.io/s/nifty-frost-7gurg?file=/src/App.js

For the other requests give me more time to think about it.

sickdyd commented 3 years ago

Hello @amaioru0!

I added the onHover prop that will display the result the user is hovering (version 5.1.0). Checkout the demo to see it in action: https://sickdyd.github.io/react-search-autocomplete/

madaher-dev commented 3 years ago

I think the component still takes the previous values. In my scenario i am calling an external API with onSearch which populates a Redux state. When i search for "Test" the component looks for Test in key of the items in the state. This causes an issue when you quickly type a long string. I will post my code below:

const SearchBar = ({ getUsers, users }) => {

const handleOnSearch = (string) => { // onSearch will have as the first callback parameter // the string searched and for the second the results.

getUsers(string);

};

return ( <div style={{ paddingTop: 20, paddingRight: 20 }}> <ReactSearchAutocomplete items={users} onSearch={handleOnSearch} onHover={handleOnHover} onSelect={handleOnSelect} onFocus={handleOnFocus} fuseOptions={{ keys: ['name', 'handler', 'bio'], shouldSort: false }} placeholder="Search Toksho" styling={{ iconColor: '#A74A5A' }} />

); }; I would be happy to deploy it for you to see it in action.

pcatach commented 3 years ago

I am also making an API request in handleOnSearch. Then I use the results of the API request to populate items. The desired behaviour would be the available items in the items array changing as the user types into the search box.

The problem I had was that the first call to handleOnSearch always resulted in an empty array of results. It only updated after the second call.

I might be wrong, but I think this component was designed to work with a static array of items instead of a dynamic one. That's the reason why, for example, handleOnSearch is supposed to receive two arguments: the input string and the array of results - so it wouldn't make sense to update the results once again inside that function. Thus we have this behaviour where the results are only updated after the second call.

The solution for me was removing the results?.length > 0 check on https://github.com/sickdyd/react-search-autocomplete/blob/4681d016fcaf23c877e0da74ad57111ca4fe97f1/src/components/ReactSearchAutocomplete.js#L67

Removing this check means that the results can be set on the first call to handleOnSearch and the delay I described above doesn't happen. Of course, this also means that if 1. user entered input 2. results are displayed and 3.items array is changed, the new results will be displayed instead of staying hidden.

sickdyd commented 3 years ago

@pcatach Yes, the idea was to have a static array of items. So what is your API request doing? Is that already a search?

pcatach commented 3 years ago

@sickdyd correct, the API request returns the results of a search. I understand that's not exactly the intention for this component

sickdyd commented 2 years ago

I will close this issue since the component is not designed to populate results after a search done with an API request, but rather to search through a static list of elements. It wouldn't make sense to search twice (once with the API request and once in the component) on the same list.