Как добавить Google API скрипт при рендеринге компонента? - PullRequest
0 голосов
/ 28 декабря 2018

Я пытаюсь добавить скрипт Google API программно, когда это требуется.Однако я получаю сообщение об ошибке, что Google не определен.Я вижу, что скрипт добавляется до конца тега body.

Ранее у меня был загружен скрипт в файл 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);

  }

Ниже приведен код для компонента, где GoogleКарта используется, и она является подкомпонентом вышеуказанного основного компонента:

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

Пожалуйста, помогите!Заранее спасибо.

1 Ответ

0 голосов
/ 28 декабря 2018

В приведенном выше фрагменте я вижу, что каждый раз, когда 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.

Использование этого не покажет вам исключение для многократного использования тега script.

Также, если вы хотите знать, что тег script загруженили нет, вы можете найти его, добавив другой метод, похожий на метод 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", выможете попробовать следовать подходу, в котором вы создаете обещание для API Карт Google, и разрешить это обещание в (глобальной) функции обратного вызова, которую может запустить API Карт Google.В коде компонента вы должны дождаться разрешения обещания, прежде чем продолжить.

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