web-dev-qa-db-ja.com

ReactコンポーネントでGoogleマップを使用する

ReactコンポーネントでGoogleマップを使用しようとしていますが、機能していないようです。現在、 https://developers.google.com/maps/documentationを参照しています。/javascript/adding-a-google-map

コンポーネントに使用するコードは次のとおりです。

class ContactBody extends React.Component {
  componentWillMount() {
    const script = document.createElement("script");
    const API = 'AIzaSyDbAz1XXxDoKSU2nZXec89rcHPxgkvVoiw';
    script.src = `https://maps.googleapis.com/maps/api/js?key=${API}&callback=initMap`;
    script.async = true;

    document.body.appendChild(script);
  };

  initMap() {
    const uluru = {lat: -25.363, 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() {
    
    this.initMap();
    
    return (
      <div>
        <h1>Contact</h1>
        <div id="map" style={{width: 400, height: 300}}></div>
      </div>
    )
  }
}

ReactDOM.render(
  <ContactBody />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="react"></div>

しかし、これを実行すると、「Uncaught ReferenceError:google is not defined」というメッセージが表示されます

誰でも私のコードの何が問題なのか教えてもらえますか?

ありがとうございました。

9
Eunicorn

ドキュメントに<script>タグを追加してGoogle Maps APIをロードしていますが、initMapメソッドを実行する前に実際にロードされるのを待っていません。まだロードされていないため、google変数はまだ存在していません。

callbackを使用して、スクリプトのURL initMapにパラメーターを追加しました。 Google Maps APIはこれを確認し、準備ができたらinitMapという関数を実行します。しかし、yourinitMapメソッドはグローバルスコープから使用できないため、実行されません。

コードを修正する1つの方法は、Google Maps APIの約束を自分のものにし、Google Maps APIが実行できる(グローバル)コールバック関数でその約束を解決することです。コンポーネントコードでは、先に進む前にプロミスが解決されるのを待ちます。

次のようになります。

class ContactBody extends React.Component {
  getGoogleMaps() {
    // If we haven't already defined the promise, define it
    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 = 'AIzaSyDbAz1XXxDoKSU2nZXec89rcHPxgkvVoiw';
        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.getGoogleMaps();
  }

  componentDidMount() {
    // Once the Google Maps API has finished loading, initialize the map
    this.getGoogleMaps().then((google) => {
      const uluru = {lat: -25.363, 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>
        <h1>Contact</h1>
        <div id="map" style={{width: 400, height: 300}}></div>
      </div>
    )
  }
}

ReactDOM.render(
  <ContactBody />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="react"></div>
19
tremby

これは私がやった方法です:

import React from 'react';

export default class GoogleMap extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      mapIsReady: false,
    };
  }

  componentDidMount() {
    const ApiKey = 'XXXXXXXXXXXXXXXXXXXX';
    const script = document.createElement('script');
    script.src = `https://maps.googleapis.com/maps/api/js?key=${ApiKey}`;
    script.async = true;
    script.defer = true;
    script.addEventListener('load', () => {
      this.setState({ mapIsReady: true });
    });

    document.body.appendChild(script);
  }

  componentDidUpdate() {
    if (this.state.mapIsReady) {
      // Display the map
      this.map = new window.google.maps.Map(document.getElementById('map'), {
        center: {lat: -34.397, lng: 150.644},
        zoom: 12,
        mapTypeId: 'roadmap',
      });
      // You also can add markers on the map below
    }
  }

  render() {
    return (
      <div id="map" />
    );
  }
}
6
Michael Yurin

エラーが発生している人のために、グーグルはeslintによって言及されたエラーのすぐ上に定義されていません

const google = window.google;
5
Rida

スクリプトをヘッドタグに追加します(推奨は react-helmet )。次に、スクリプトsrcで定義するためにwindow.initMapを初期化関数に等しくします(callback=initMap")「initMap」という名前のグローバル関数。

import React, { useEffect } from 'react';
import { Helmet } from 'react-helmet';

const Map = () => {
  useEffect(() => {
    window.initMap = () => {
      new google.maps.Map(document.getElementById('map'), {
        center: { lat: -34.397, lng: 150.644 },
        zoom: 8,
      });
    };
  }, []);
  return (
    <>
      <Helmet>
        <script src="https://maps.googleapis.com/maps/api/js key=?key=YOUR_API_KEY&callback=initMap" async defer />
      </Helmet>
      <div style={{ height: "100%" }} id="map"></div>
    </>
  );
};

windowがnode.js環境で未定義であるため、サーバー側でレンダリングする必要がある場合、ブラウザ環境にある必要があります。

... lang-js
if (process.browser) { // check browser environment
  window.initMap = (): void => {
    new google.maps.Map(document.getElementById('map'), {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8,
    });
  };
}
...
1
Masih Jahangiri

ページの上部でこれを入力してみてください(私のために動作します)-/ *グローバルgoogle * /

0

index.htmlにGoogle APIスクリプトを含める場合、createElement componentDidMount()内。このようなことができます

import React from 'react';
export default class GoogleMap extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      mapIsReady: false,
    };
  }

  componentDidMount() {
    //Load Map after DOM is loaded
    window.onload = this.setState({mapIsReady : true});
  }

  componentDidUpdate() {
    if (this.state.mapIsReady) {
      // Display the map
      this.map = new window.google.maps.Map(document.getElementById('map'), {
        center: {lat: -34.397, lng: 150.644},
        zoom: 12,
        mapTypeId: 'roadmap',
      });
      // You also can add markers on the map below
    }
  }

  render() {
    return (
      <div id="map"></div>
    );
  }
}
0
Parvez Siddiqi