Reputation: 175
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))
}
Upvotes: 10
Views: 21978
Reputation: 6128
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.
Upvotes: 17