I am working with react and the component autocomplete of material-ui, I need help with the following problem.
In the examples of autocomplete I saw you need to have all elements of the list in the frontend to use the autocomplete, in my case I get the list from a web service and it could be huge, so instead of searching for the whole list I want that every time a letter is typed in the autocomplete it generates a search to the web service filtering names according to the input that is being written and with a max results of 10 elements. The endpoint of the webservice already has a filter property where you can pass the quantity of results you want and the letters you want of the name.The only thing that the autocomplete has to do is everytime you type a letter it hits the endpoint (filtering with the word that is being typed) and updates the list of elements of the autocomplete.
Right now I have the following code, the problem is that it searches the whole list when you click the autocomplete but when you type each letter it doesn't do anything.
import Autocomplete from '@material-ui/lab/Autocomplete';
import TextField from '@material-ui/core/TextField';
import CircularProgress from '@material-ui/core/CircularProgress';
const [open, setOpen] = React.useState(false);
const [organizationList, setOrganizationList] = React.useState([]);
const loading = open && organizationList.length === 0;
React.useEffect(() => {
let active = true;
if (!loading) {
return undefined;
}
(async () => {
if (active) {
try {
setOrganizationList(await api.post('/v1/organizations/search', {maxResults:10}));
} catch (error) {
snackbar.showMessage(error, "error");
}
}
})();
return () => {
active = false;
};
}, [loading]);
React.useEffect(() => {
if (!open) {
setOrganizationList([]);
}
}, [open]);
The definition of the autocomplete:
<Autocomplete
id="asynchronous-demo"
style={{ width: 300 }}
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
getOptionSelected={(option, value) => option.orgName === value.orgName}
getOptionLabel={(option) => option.orgName}
options={organizationList}
loading={loading}
renderInput={(params) => (
<TextField
{...params}
label="Asynchronous"
variant="outlined"
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{loading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}}
/>
)}
/>
To hit the endpoint I have this:
setOrganizationList(await api.post('/v1/organizations/search', {maxResults:10}));
I need to pass the input of the autocomplete every time a letter is typed, like this:
setOrganizationList(await api.post('/v1/organizations/search', {name:inputAutocomplete,maxResults:10}));
Thanks a lot for the help. Im new to react by the way.
In material-ui
library Autocomplete
component has a props onChange
that can be used like this.
onChange={(event, newValue) => {
setValue(newValue);
}}
You should be interested in the second parameter newValue
. Thus, you will receive a new input value every time a letter is typed.
Therefore, just move the logic for getting the list into this callback.
You can read more about controllable state in the material-ui
documentation