react-places-autocomplete
react-places-autocomplete copied to clipboard
Library implemented management of google maps dependency: asynchronous loading and unmounting
Do you want to request a feature or report a bug? Feature / bug
What is the current behavior? By default, this library does not load the google maps library asynchronously. There is, however, a user provided solution to do so (pasted in 'minimal demo' below).
This solution, however, does not handle any unmounting, and we are left with google.maps on the window scope and about 7 extra <script /> elements added to the document.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.
state = {
gmapsLoaded: false,
}
initMap = () => {
this.setState({
gmapsLoaded: true,
})
}
componentDidMount () {
window.initMap = this.initMap
const gmapScriptEl = document.createElement(`script`)
gmapScriptEl.src = `https://maps.googleapis.com/maps/api/js?key=SECRET_EATING&libraries=places&callback=initMap`
document.querySelector(`body`).insertAdjacentElement(`beforeend`, gmapScriptEl)
}
componentWillUnmount() {
// we should be doing something here
}
render () {
return (
<div>
{this.state.gmapsLoaded && (
<PlacesAutocomplete />
)}
</div>
)
}
What is the expected behavior?
- [x] we should be able to load the script asynchronously
- [ ] this library should load the script asynchronously for us (maybe add a
skipInjectprop to prevent this behavior and allow the user to inject themselves) - [ ] this library should remove the google maps when the component unmounts
Proposed Solution I think I need to sleep on this one a bit more, and it wasn't entirely clear from the google maps documentation how to do this. I have an approach that seems like it might work, but feedback would be greatly appreciated:
componentWillUnmount() {
// remove all 'maps.googleapis.com' scripts injected into the document
// hat tip: https://stackoverflow.com/a/9469983/5045662
// to do: i am uncertain whether this actually removes the scripts from memory,
// but if they create everything on `window.google.maps` i think we'll be ok
const tags = document.getElementsByTagName('script')
for (let i = tags.length; i >= 0; i--) {
//search backwards within nodelist for matching elements to remove
if (
tags[i] &&
tags[i].getAttribute('src') != null &&
tags[i].getAttribute('src').includes('maps.googleapis.com')
)
tags[i].parentNode.removeChild(tags[i]) //remove element by calling parentNode.removeChild()
}
// set the google.maps instance on the window to null
window.google.maps = null
}
@hibiken if you would be okay with this library also managing how to inject & remove the underlying google maps dependency, I would be happy to create a PR. Just wanted to run it by you first.
Which versions of ReactPlacesAutocomplete, and which browser / OS are affected by this issue? All
@pcooney10 Thank you for creating this issue! Let me look into this a bit to see if it makes sense to add this to the library :)
I would be interested in this as well. You could create a utility that is publicly exported from this package.
In addition to being available as a utility it could also be a defaultProp of PlacesAutocomplete that PlacesAutocomplete uses to load the necessary scripts. Something similar to https://github.com/google-map-react/google-map-react/blob/master/src/loaders/google_map_loader.js
but maybe with the addition of a callback method that exposes the maps object - similar to https://github.com/google-map-react/google-map-react/blob/master/src/google_map.js#L545