react-google-autocomplete
react-google-autocomplete copied to clipboard
Language prop is not reactive
The language can not be changed dynamically.
I realize this is because of a limitation in the Google Places Lib and the fact that the language is a parameter of the script URL itself:
https://github.com/ErrorPro/react-google-autocomplete/blob/214a7c3d4740d2bfcf85264717b0e0da5bd0b333/src/usePlacesWidget.js#L33
This means that this affects changing the language dynamically and also using two different languages on the same site.
Reproduction Example
function MyComponent() {
const [lang, setLang] = useState("en");
return (
<>
<button type="button" onClick={() => setLang("en")}>
EN
</button>
<button type="button" onClick={() => setLang("de")}>
DE
</button>
<Autocomplete
apiKey={YOUR_GOOGLE_MAPS_API_KEY}
language={lang}
onPlaceSelected={(place) => console.log(place)}
/>
</>
);
}
Workaround
function unloadGooglePlacesLib() {
// Only if the lib is loaded
if (window.google && window.google) {
// in theory deleting window.google.maps should be enough but react-google-autocomplete only checks for window.google
// https://github.com/ErrorPro/react-google-autocomplete/blob/214a7c3d4740d2bfcf85264717b0e0da5bd0b333/src/utils.js#L20
// this will break if you use other google libs
delete window.google;
document
.querySelectorAll('script[src*="https://maps.googleapis.com"]')
.forEach((scriptEl) => {
scriptEl.remove();
});
// Needed to unload
return true;
}
// Didn't need to do anything
return false;
}
function MyComponent() {
const [forceRerender, setForceRerender] = useState(false);
const [lang, setLang] = useState("en");
useEffect(() => {
setForceRerender(false);
}, [forceRerender]);
// Props of the ReactGoogleAutocomplete end up as params of the Google Maps Places API script (the lib) that
// is downloaded. When changing the props and even when recreating the component, these param changes don't
// have any effect. To fix this we remove the scripts and recreate the component. This reloads the scripts.
useEffect(() => {
const neededToUnload = unloadGooglePlacesLib();
setForceRerender(neededToUnload);
}, [lang]);
return (
<>
<button type="button" onClick={() => setLang("en")}>
EN
</button>
<button type="button" onClick={() => setLang("de")}>
DE
</button>
{!forceRerender && (
<Autocomplete
apiKey={YOUR_GOOGLE_MAPS_API_KEY}
language={lang}
onPlaceSelected={(place) => console.log(place)}
/>
)}
</>
);
}
Proposed Solutions
- Dynamically reload the script like done in the workaround (this won't solve using different languages on the same site)
- Try to isolate the script somehow so multiple language versions can exist in parallel (not sure if this is even possible)
- Admit defeat but at least show a warning and document this limitation
Yeah, good point, I'll try to implement the proposed solution. It indeed will require a reload of google maps api with a new language, which should block any iteration with the API until after the script is loaded.