I have this Autocomplete component
<Autocomplete
filterOptions={(x) => x}
options={items}
getOptionLabel={(option) =>
`${option.code} - ${option.name}`
}
onInputChange={(e, value) => {
console.log(value);
setAutoComplete(value);
}}
onChange={(e, value) => {
//Change state of some other fields
}}
noOptionsText={false}
renderInput={(params) => (
<TextField
{...params}
/>
)}
value={
items.filter((item) => item.id == row.item_id)[0] || null
}
/>
I’m trying to make a server search and get the new items
value, the problem is that this results in an infinite loop as when the value of the autocomplete is changed to another item, the onInputChange
is also called, Making another request to get the new items
value thus making changing input again and again until the server hangs up on the request.
However, this only happens when the value
of the Autocomplete
is controlled, I have another component that’s uncontrolled and it doesn’t produce this infinite loop.
How can I fix this?
2
Answers
So this might seem weird. But I fixed the error by setting the
setAutocomplete
to take the value of thee?.target.value
of theonInputchange
function, instead of the value itself. This somehow fixed the problem.This happens because the reference to the selected object in
value
keeps changing.When you download a new list of items and filter the item from the new list in the
value
prop, even though the contents of the items are identical, the new item is a different object in the browser’s memory. MUI interprets it as a value change so it triggers theonInputChange
callback, which causes new data to fetch, which causes the value to change, … – you get an infinite loop.Here is a CodeSandbox I prepared that demonstrates the issue: https://codesandbox.io/s/peaceful-dawn-928gg2?file=/src/Demo.tsx
I think the easiest way to fix that would be to use the IDs of your items as options (instead of entire objects) and then find the correct item inside the
getOptionLabel
function.IDs are strings or numbers (primitive types) so they are compared by value instead of by reference, which means that the issue will be solved. This solution will not work if your ID field is an object or an array!
That would mean changing the following props in your code:
You might also need to make changes to the
onInputChange
prop and handleundefined
/null
ingetOptionLabel
andvalue
but it’s difficult to tell exactly without seeing more of your code.You can learn more about that issue in the documentation: https://mui.com/material-ui/react-autocomplete/#controlled-states (see the yellow warning section)