My Google Books clone application has a user submit their inputted query
, then the response data
is displayed.
I'd like to implement Downshift
's search autocomplete feature so that as the user
types their query
, a drop down list of suggestions matching their current query
is listed. Clicking on a list item from the drop down suggestion list should update the input query, then fetch data
for that query
. I desire the same behavior as Google Books
The data from the example in the Downshift
docs is hard-coded. In my case, data
is empty prior to the fetch
.
I figured I'd need to create a suggestions object and define the useCombobox
logic to fetch suggestions on every input change. Then assign handleBookFetch
to the drop down list's items' onClick
. With this attempt, I receive TypeErrorCannot read property 'length' of undefined
.
I'm having trouble trying to figure out how to use it in my instance. How do I go about fetching suggestions as the user types a query into the input, then update the query value with the clicked suggestion and also fetch the query for the clicked suggestion? CodeSandbox
const [query, setQuery] = useState("");
const [books, setBooks] = useState({ items: [] });
const [suggestions, setSuggestions] = useState({ suggestionItems: [] });
useCombobox({
suggestions: suggestions,
onInputValueChange: ({ inputValue }) => {
const fetchSuggestions = async () => {
try {
const result = await axios.get(`${API_BASE_URL}?q=${query}`);
setSuggestions(result.data);
} catch (isError) {
setIsError(true);
}
};
fetchSuggestions();
setSuggestions(
suggestions.suggestionItems.filter((suggestionItem) =>
suggestionItem.toLowerCase().startsWith(inputValue.toLowerCase())
)
);
const handleBookFetch = (event) => {
const fetchBooks = async () => {
try {
const result = await axios.get(`${API_BASE_URL}?q=${query}`);
setBooks(result.data);
} catch (isError) {
setIsError(true);
}
};
fetchBooks();
};
<form onSubmit={handleBookFetch}>
<div className={comboboxStyles} {...getComboboxProps()}>
<input
type="text"
value={query}
onChange={(event) => setQuery(event.target.value)}
{...getInputProps()}
/>
<button
type="button"
{...getToggleButtonProps()}
aria-label="toggle menu"
>
↓
</button>
<button type="submit">Search</button>
</div>
<ul {...getMenuProps()} style={menuStyles}>
{isOpen &&
suggestions.suggestionItems.map((book, index) => (
<li
style={
highlightedIndex === index
? { backgroundColor: "#bde4ff" }
: {}
}
key={`${book}${index}`}
onClick={handleFetchBook}
{...getItemProps({ book, index })}
>
{book.volumeInfo.title}
</li>
))}
</ul>
</form>