React autocomplete component with an opinionated UX.
- Allows retrieving of autocomplete results asynchronously from an API
- Responds to keyboard and mouse inputs the way you’d expect
- ↑ or ↓ — Highlight the previous or next autocomplete result, if any, and update the text box value with the value of the highlighted item.
- Esc — Unfocus the text box, and hide the autocomplete results, if any.
- Enter — Execute the Enter key down callback (namely,
onEnterKeyDown
). - If the text box value changes — Executes the callback to retrieve results for the text box value (namely,
getResultList
), and updates the autocomplete results. Execution of this callback is appropriately debounced to avoid unnecessary API calls. - Clicking on an autocomplete result — Sets the highlighted item to the item that was clicked, and executes the
onClick
callback (namely,onResultItemClick
).
- Flexible and extensible
- Exposes class name hooks to allow styling of respective parts of the component.
- Exposes assorted render callbacks to insert elements at specific locations in the component.
- Performant
- Caches autocomplete results by default
The following is a barebones usage example with just the three required props
, assuming a /search
endpoint to obtain autocomplete results.
import AutoComplete from '@yuanqing/autocomplete';
import React from 'react';
import {render} from 'react-dom';
render((
<AutoComplete
getResultItemValue={function(resultItem) {
return resultItem.value;
}}
getResultList={function(value) {
return window.fetch(`/search?q=${value}`)
.then((response) => {
return response.json();
});
}}
renderResultItem={function(resultItem) {
const {
link,
value
} = item;
return <a href={link}>{value}</a>;
}}>
<input aria-autocomplete="both" role="combobox" type="text" />
</AutoComplete>
), document.querySelector('.autoComplete'));
The example in the repo is a working autocomplete search box that returns results from Wikipedia.
To run it, do:
$ git clone
$ npm install
$ npm install --global gulp
$ gulp example --open
import AutoComplete from '@yuanqing/autocomplete';
N.B. All the props
that are functions are always called with their this
context set to the AutoComplete
instance.
- Signature:
(resultItem)
Function that yields the value from resultItem
that is to be assigned to the text box when said resultItem
is highlighted.
- Signature:
(value)
Function that returns a Promise for an array of results that match the given value
.
- Signature:
(resultItem)
Function that returns a ReactElement
to be rendered corresponding to the given resultItem
.
The text box element.
-
Default:
<input aria-autocomplete="both" role="combobox" type="text" />
An object literal of classes to assign to the various elements that compose the autocomplete.
-
Default:
{ // Class added to the currently highlighted result item isHighlighted: 'isHighlighted', // Class added to the outermost wrapper `div` when waiting for the `getResultList` // Promise to be fulfilled isLoading: 'isLoading', // Class of each result item resultItem: 'resultItem', // Class of the `div` that contains all the result items resultList: 'resultList', // Class of the root `div` root: 'root', // Class of the `div` that contains the text box (ie. the `children` prop) textBox: 'textBox' }
getResultList
is called if and only if the value of the text box has not changed for the specified debounceDuration
.
- Default:
250
Function that is called when we press the Enter key while the text box is focused.
- Default:
undefined
- Signature:
(value, highlightedResultItem)
Function that is called when we click on a result item.
- Default:
undefined
- Signature:
(resultItem)
Functions that return a ReactElement
to be inserted at respective locations in the component.
- Default:
undefined
Whether results should be cached. If true
, use results from the cache instead of hitting the API endpoint. (The cache is an object that maps each value to an array of result items.)
- Default:
true
Install via npm:
$ npm i --save @yuanqing/autocomplete