I'm using the Material UI Autocomplete component to make an API call in a method that returns a JSON. The idea is that when the user types in the autocomplete component it makes a call to find the results matching the string.
The problem I have with the code I put is that I don't know how to make the API call and return the results in the autocomplete component
const [itemsAutocomplete, setItemsAutocomplete] = useState([])
<Autocomplete
disablePortal
id="autocomplete-search"
onChange={handleItemsOptions}
getOptionLabel={option => option.name}
sx={{ width: 300 }}
renderInput={params => (
<TextField {...params} label="Search an item..." />
)}
/>
const handleItemsOptions = event => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name : search_name,
}),
}
fetch(
`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/product/items/search/`,
requestOptions,
)
.then(response => response.json())
.then(json => setItemsAutocomplete(json))
}
If you want to update the options every time the user types into the search box, you could use the onInputChange property of the Autocomplete and hook that up to a function which performs the API call and updates the options based on the results.
HTML
<Autocomplete
id="combo-box-demo"
options={options}
onInputChange={onInputChange}
getOptionLabel={(option) => option.title}
style={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="Combo box" variant="outlined" />
)}
/>
Javascript
const [options, setOptions] = useState([]);
const previousController = useRef();
const getData = (searchTerm) => {
if (previousController.current) {
previousController.current.abort();
}
const controller = new AbortController();
const signal = controller.signal;
previousController.current = controller;
fetch("https://dummyjson.com/products/search?q=" + searchTerm, {
signal,
headers: {
"Content-Type": "application/json",
Accept: "application/json"
}
})
.then(function (response) {
return response.json();
})
.then(function (myJson) {
console.log(
"search term: " + searchTerm + ", results: ",
myJson.products
);
const updatedOptions = myJson.products.map((p) => {
return { title: p.title };
});
setOptions(updatedOptions);
});
};
const onInputChange = (event, value, reason) => {
if (value) {
getData(value);
} else {
setOptions([]);
}
};
onInputChange will perform an HTTP request (getData(value)) if the user has typed something. If the string is empty (i.e. the user has deleted the text they typed) it will default the options to the empty array. In this function, value is the string the user has typed.
getData performs an HTTP request and calls setOptions to update the autocomplete options based on the results returned. The use of AbortController is to ensure that when the user types (or deletes) a character and the next HTTP request is made, previous HTTP requests are cancelled. This is because depending on the speed of the API, requests may not return in the order they are sent.
See this CodeSandbox for a working demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With