1

我正在尝试在需要时以编程方式添加 google api 脚本。但是,我收到一个错误,即未定义 google。我可以看到脚本是在正文标记结束之前添加的。

之前我在 index.html 文件中加载了脚本,但是,我现在在应用程序的其他地方创建了一个不同的组件,它需要自己的脚本,因为它有不同的 api 密钥。因此,我不得不从 index.html 中删除该脚本,因为它为多次使用该脚本提供了一个例外。现在我想在加载组件时添加它。

主要组件请参考以下代码:

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);

  }

以下是使用谷歌地图的组件的代码,它是上述主要组件的子组件:

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>
    );
  }
}

请帮忙!提前致谢。

4

1 回答 1

0

在上面的代码片段中,我可以看到每次 componentDidMount 都会再次创建另一个脚本标签以避免这种情况,您可以修改 loadScript 方法如下:

const loadScript = (url) => {
    const googleScript = window.document.getElementByClassName('google-script');
    if (googleScript.length === 0) {
        const script = window.document.createElement('script');
        script.src=url;
        script.class="google-script"
        document.body.appendChild(script)
    }
}

如果您想删除 google 脚本,您可以在 componentWillUnmount 中进行处理。

使用它不会向您显示脚本标签多次使用的例外情况。

此外,如果您想知道脚本标签是否已加载,您可以通过在 loadScript 方法中添加另一个类似的方法来找到它,如下所示:

const loadScript = (url) => {
    const googleScript = window.document.getElementByClassName('google-script');
    if (googleScript.length === 0) {
        const script = window.document.createElement('script');
        script.src=url;
        script.class="google-script"
        document.body.appendChild(script)
        script.onload = () => {
            // Place code here to do further action.
        };
    }
}

<----------------------------更新-------- -------->

为了解决“google is undefined”错误,您可以尝试按照为 Google Maps API 创建承诺的方法,并在 Google Maps API 可以运行的(全局)回调函数中解决该承诺。在您的组件代码中,您将等待承诺得到解决,然后再继续。

const loadScript = () => {
  if (!this.googleMapsPromise) {
    this.googleMapsPromise = new Promise((resolve) => {
      // Add a global handler for when the API finishes loading
      window.resolveGoogleMapsPromise = () => {
        // Resolve the promise
        resolve(google);

        // Tidy up
        delete window.resolveGoogleMapsPromise;
      };

      // Load the Google Maps API
      const script = document.createElement("script");
      const API = //your api key;
        script.src = `https://maps.googleapis.com/maps/api/js?key=${API}&callback=resolveGoogleMapsPromise`;
      script.async = true;
      document.body.appendChild(script);
    });
  }

  // Return a promise for the Google Maps API
  return this.googleMapsPromise;
}



componentWillMount() {
  // Start Google Maps API loading since we know we'll soon need it
  this.loadScript();
}

componentDidMount() {
  // Once the Google Maps API has finished loading, initialize the map
  this.getGoogleMaps().then((google) => {
    const uluru = { lat: -25.366, lng: 131.044 };
    const map = new google.maps.Map(document.getElementById('map'), {
      zoom: 4,
      center: uluru
    });
    const marker = new google.maps.Marker({
      position: uluru,
      map: map
    });
  });
}

render() {
  return (
    <div>
      <div id="map" style={{width: 600, height: 300}}></div>
    </div>
  )
}
于 2018-12-28T14:26:51.023 回答