Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order search results in react-select

When using react-select, search results are ordered alphabetically by default. This is a good default but not so nice if I have an exact match that is not first alphabetically. For example, a user may have the following options:

  • a_react
  • b_react
  • c_react
  • d_react
  • react

With these options, the user may search for 'react' and not be any closer to selecting the option that exactly matches the search term. Is there any way to optimize for exact matches?

like image 938
Brady Dowling Avatar asked Jul 24 '19 21:07

Brady Dowling


3 Answers

In react-select you can pass a filterOption property to change how the filtering works. They provide a nice api to do what you want, which is start matching from the beginning of the string rather than anywhere in the string. That would look something like this

filterOption={createFilter({ matchFrom: "start" })}

where createFilter is imported from react-select

like image 66
John Ruddell Avatar answered Oct 18 '22 22:10

John Ruddell


react-select has a prop if you want to have a custom filter - filterOption.

If you want to show better matches based on what a user queries, use match-sorter in combination with onInputChange of react-select to create a custom filter. Here's a working demo.

There are two select inputs. Type l and observe the difference in suggestions.

like image 33
ron4ex Avatar answered Oct 18 '22 20:10

ron4ex


@ron4ex has a great answer here. Just wanted to offer another similar solution as I had 1 big issue with match-sorter.

Issue with match-sorter:

  • My list is a list of family relationships, e.g. "mother", "mother-in-law"
  • match-sorter would prioritize mother-in-law over mother as I started typing. Only once it was a full match would it prioritize mother. However, react-select kept the focused option as mother-in-law.
  • Even if I could fix the default focus issue, I would rather "mot" match to "mother" before "mother-in-law".

Enter new solution: Fuse:

  • Similar implementation as match-sorter
  • Fuzzy search with lots of customization options
  • Default config sorted "mother" over "mother-in-law"
const fuse = new Fuse(relationshipTypes, { keys: ["label"] });

<Select>
  onInputChange={inputValue => {
    setRelationshipOptions(
      fuse.search(inputValue).map(value => value.item)
    );
  }}
</Select>
  • notice the map on fuse.search as fuse returns a mutated array with the original values in an item key and a second key being the index. Hence, fuse.search().map
like image 1
Sharud Avatar answered Oct 18 '22 21:10

Sharud