react-google-autocomplete
react-google-autocomplete copied to clipboard
onPlaceSelected callback is not reactive
If the <ReactGoogleAutocomplete> component rerenders, the onPlaceSelected is not updated reaxtively.
This is important in many cases where you have a callback that relies on some state.
This is because the event listener: https://github.com/ErrorPro/react-google-autocomplete/blob/214a7c3d4740d2bfcf85264717b0e0da5bd0b333/src/usePlacesWidget.js#L72-L75
...is only updated in the "init" useEffect that has no dependencies:
https://github.com/ErrorPro/react-google-autocomplete/blob/214a7c3d4740d2bfcf85264717b0e0da5bd0b333/src/usePlacesWidget.js#L93-L95
Reproduction Example
function MyComponent() {
const [someState, setSomeState] = useState(false);
// "toggleState" assinged a new function everytime "someState" changes
const toggleState = useCallback(() => {
const newState = !someState;
setSomeState(newState);
console.log("new state is", newState);
}, [someState]);
// "onPlaceSelected" is assinged a new function everytime "toggleState" changes
const onPlaceSelected = useCallback(
(place) => {
console.log(place);
toggleState();
},
[toggleState]
);
return (
<ReactGoogleAutocomplete
apiKey={YOUR_GOOGLE_MAPS_API_KEY}
// onPlaceSelected is not updated in subsequent renders
onPlaceSelected={onPlaceSelected}
/>
);
}
toggleState() will always set someState to true.
Workaround
Using useEffect and useRef you can workaround this:
function MyComponent() {
const [someState, setSomeState] = useState(false);
const onPlaceSelected = useRef(() => undefined);
// "toggleState" assinged a new function everytime "someState" changes
const toggleState = useCallback(() => {
const newState = !someState;
setSomeState(newState);
console.log("new state is", newState);
}, [someState]);
// "onPlaceSelected" is assinged a new function everytime "toggleState" changes
useEffect(() => {
onPlaceSelected.current = (place) => {
console.log(place);
toggleState();
};
}, [toggleState]);
return (
<Autocomplete
apiKey={YOUR_GOOGLE_MAPS_API_KEY}
// onPlaceSelected is not updated in subsequent renders
onPlaceSelected={(...args) => onPlaceSelected.current(args)}
/>
);
}
Good one, will check it as well
Thank you for looking into all the issues!
hi, is there a fix for this?