I am using the following code to render a Material UI AutoComplete
field with options retrieved from an API. I would like to prevent re-rendering of the input field but the chosen country is used as a prop
for the Country
component which should be updated onChange
. set_alpha3Code
doesn't seem to update the state from within useCallback
. How do I get around that?
let AC = memo(AutocompleteCountries)
function Show(props: {})
{
let [alpha3Code_, set_alpha3Code_] = useState<string>('gbr');
let onChange = useCallback((alpha3Code) => {
console.log(alpha3Code_);
set_alpha3Code_(alpha3Code);
}, []);
return (
<div>
<AC onChange={onChange}/>
{alpha3Code_ ? <Country cca3_={alpha3Code_}/> : null}
</div>
)
}
CodePudding user response:
Two things jump out about that code:
onChange
withoutvalue
- Stale state
onChange
without value
In the normal case, if you specify onChange
with an input control, you have to specify value
to tell the control what the current (updated) value is. The documentation for Material-UI's Autocomplete
definitely suggests you need both:
Controlled states
The component has two states that can be controlled:
- the "value" state with the
value
/onChange
props combination. This state represents the value selected by the user, for instance when pressing Enter.
The same thing with a standard input
prevents the input from ever changing. I haven't used the Material-UI Autocomplete
, but I suspect it's similar.
Stale state
Your code is updating the value of alpha3Code_
(if onChange
is called with a new value), but the console.log
in that code looks at at an old one:
let onChange = useCallback((alpha3Code) => {
console.log(alpha3Code_); // <−−− Uses the *first* `alpha3Code_` only
set_alpha3Code_(alpha3Code);
}, []);
// ^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Because you haven't included
// `alpha3Code_` in these dependencies
But even though that console.log
shows you outdeated information, the rest of the code is fine and will work. It will re-render the AC
with the updated code.
If you want to see the alpha3Code_
used for rendering, put a breakpoint on the return
and look at it in the debugger (or move the console.log
outside the onChange
handler to above the return
).
CodePudding user response:
Thank you. Apologies for the question. The problem was within the useEffect
dependencies of the Country
component.