简体   繁体   English

在 React 组件中使用 Google Map

[英]Using Google Map in React Component

I am trying to use Google Map in React Component and it doesn't seem to work.我正在尝试在 React Component 中使用 Google Map,但它似乎不起作用。 I am currently referring to https://developers.google.com/maps/documentation/javascript/adding-a-google-map我目前指的是https://developers.google.com/maps/documentation/javascript/adding-a-google-map

Here is the code that I have for my component:这是我的组件的代码:

 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>

However, when I run this, I am getting "Uncaught ReferenceError: google is not defined"但是,当我运行它时,我收到“Uncaught ReferenceError: google is not defined”

Could anyone tell me what is wrong with my code?谁能告诉我我的代码有什么问题?

Thank you.谢谢。

You're adding a <script> tag to your document to load the Google Maps API, but you aren't waiting for it to actually load before running your initMap method.您在文档中添加了一个<script>标签以加载 Google Maps API,但在运行initMap方法之前您并没有等待它实际加载。 Since it hasn't loaded yet, the google variable doesn't yet exist.由于尚未加载,因此google变量尚不存在。

You've added a parameter to the script's URL, callback , with a value initMap .您已向脚本的 URL 中添加了一个参数callback ,其值为initMap The Google Maps API will see this and run a function called initMap once it's ready. Google Maps API 将看到这一点并在它准备好后运行一个名为initMap的函数。 But your initMap method is not available from the global scope, and so will not be run.但是您的initMap方法在全局范围内不可用,因此不会运行。

One way to fix your code would be to make yourself a promise for the Google Maps API, and resolve that promise in a (global) callback function the Google Maps API can run.修复代码的一种方法是让自己对 Google Maps API 做出承诺,并在 Google Maps API 可以运行的(全局)回调函数中解决该承诺。 In your component code you'd then wait for the promise to be resolved before proceeding.在您的组件代码中,您将在继续之前等待承诺得到解决。

That might look something like this:这可能看起来像这样:

 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>

This is how I did it:我是这样做的:

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

对于那些遇到错误的人,谷歌没有定义在 eslint 提到的错误之上,继续定义

const google = window.google;

Add script to head tag (my recommend is react-helmet ) then equal window.initMap to your initialize map function because in script src define ( callback=initMap" ) a global function named 'initMap'.将脚本添加到 head 标记(我的推荐是react-helmet )然后将 window.initMap 等于您的初始化映射函数,因为在脚本 src 中定义( 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>
    </>
  );
};

If in server side rendered must check is in browser environment because window in undefined in node.js environment:如果在服务器端渲染必须检查浏览器环境,因为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,
    });
  };
}
...

If you are including Google API Script in your index.html then there is no need to createElement in componentDidMount().如果您在包括谷歌API的脚本在您的index.html那么就没有必要在的createElement componentDidMount()。 You can do something like this-你可以做这样的事情——

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

In react apps,在反应应用程序中,

use script tag in index.html load google maps api is NOT working, will give you error Access origin deny .....在 index.html 中使用脚本标签加载谷歌地图 api 不起作用,会给你错误访问源拒绝 .....

The work around is load google map api in downstream module system, use useEffect() hook.解决方法是在下游模块系统中加载 google map api,使用 useEffect() 钩子。

As example, I simple use app.js load api, you can use any component to do so.例如,我简单地使用 app.js 加载 api,您可以使用任何组件来执行此操作。 No need to be app.js无需成为 app.js

here is my working code:这是我的工作代码:

                 import React, { useState, useEffect } from 'react';

                  function App() {

                       useEffect(() => {


                            const googleMapScript = document.createElement('script');
                            googleMapScript.src=`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLEMAPS_API_KEY}&libraries=places&callback=initMap`;
                            googleMapScript.async = true;
                            window.document.body.appendChild(googleMapScript);

                      }); 

    return (

Do not forget to put your google map api key in .env file, so you can refer it as不要忘记将您的 google map api 密钥放在 .env 文件中,这样您就可以将其称为

              process.env.REACT_APP_GOOGLEMAPS_API_KEY

.env file should put in the root folder, same place where your package.json located, so .env file should next to package.json file. .env 文件应该放在根文件夹中,与 package.json 所在的位置相同,所以 .env 文件应该放在 package.json 文件旁边。

This is when .env file looks like:这是 .env 文件的样子:

              REACT_APP_GOOGLEMAPS_API_KEY=AIzajfU2J8m4vE 

Remember, you key must start as "REACT_APP_"请记住,您的密钥必须以“REACT_APP_”开头

尝试在页面顶部键入此内容(对我有用)- /* global google */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM