I am trying to add the google api script programmatically when it is required. However, I get an error that google is not defined. I can see that the script is added in before the end of the body tag.
Earlier I had the script loaded in the index.html file however, I have created a different component elsewhere in the app now which require its own script as it has a different api key. Therefore, I had to remove the script from the index.html as it was giving an exception for multiple use of the script. Now I would like to add it when it is the component is loading.
Please refer the code below for the main component:
import React from 'react';
import { Button } from 'reactstrap';
import CitySuggestionBar from './CitySuggestionBar';
export default class Destination extends React.Component{
componentDidMount(){
this.renderScript();
}
renderScript = () => {
loadScript('https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&libraries=places');
}
showPlaceDetails(place) {
let city = place.address_components[0].long_name.toString();
try{
city+= '+' + place.address_components[2].long_name.toString();
}catch(e){}
city = city.replace(/\s/g, "+");
sessionStorage.setItem('city', city);
console.log(city);
}
redirect = () =>{
sessionStorage.getItem('city') ? this.props.history.push("/hotels") : alert('Please select a city first');
}
render(){
return(
<div className="location-search-container">
<div className="location-search-wrapper">
<h1>Search for a city...</h1>
<CitySuggestionBar onPlaceChanged={this.showPlaceDetails.bind(this)} />
<Button onClick={this.redirect} className="btns" to="/hotels" color="primary">Proceed</Button>
</div>
</div>
);
}
}
const loadScript = (url) => {
const index = window.document.getElementsByTagName('script')[0];
const script = window.document.createElement('script');
script.src=url;
index.parentNode.insertBefore(script, index);
}
Below is the code for the component where the google map is being used and it is a sub component of the above main component:
import React from "react";
/* global google */
export default class CitySuggestionBar extends React.Component {
constructor(props) {
super(props);
this.autocompleteInput = React.createRef();
this.autocomplete = null;
this.handlePlaceChanged = this.handlePlaceChanged.bind(this);
}
componentDidMount() {
this.autocomplete = new window.google.maps.places.Autocomplete(this.autocompleteInput.current,
{"types": ['(cities)']});
this.autocomplete.addListener('place_changed', this.handlePlaceChanged);
}
handlePlaceChanged(){
const place = this.autocomplete.getPlace();
this.props.onPlaceChanged(place);
}
render() {
return (
<input ref={this.autocompleteInput} id="autocomplete" placeholder="Search"
type="text"></input>
);
}
}
Please Help! Thanks in advance.
In the above snippet, I can see that every time the componentDidMount it will again create another script tag to avoid this, you can modify the loadScript methods as follows:
If you like to remove the google script you can handle this inside componentWillUnmount.
Using this will not show you an exception for multiple uses of the script tag.
Also if you like to know that the script tag is loaded or not you can find it by adding another like in loadScript method as follows:
<----------------------------Update--------------------------->
In order to resolve "google is undefined" error you can try following the approach where you create a promise for the Google Maps API, and resolve that promise in a (global) callback function the Google Maps API can run. In your component code, you'd then wait for the promise to be resolved before proceeding.