在 React 组件中使用 Google 映射

Using Google Map in React Component

我正在尝试在 React Component 中使用 Google Map,但它似乎不起作用。 我目前指的是 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"

有人能告诉我我的代码有什么问题吗?

谢谢。

您正在向文档添加 <script> 标记以加载 Google 地图 API,但您并未在 [=44= 之前等待它实际加载]宁你的 initMap 方法。由于尚未加载,google 变量尚不存在。

您已将参数添加到脚本的 URL、callback,值为 initMap。 Google 地图 API 将在准备就绪后看到此 运行 一个名为 initMap 的函数。但是 你的 initMap 方法在全局范围内不可用,因此不会 运行.

修复代码的一种方法是为 Google 地图 API 做出自己的承诺,并在 Google 地图的(全局)回调函数中解决该承诺API 可以 运行。在您的组件代码中,您将等待 promise 在继续之前得到解决。

可能看起来像这样:

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>

我是这样做的:

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

对于那些遇到错误的人 google is not defined 就在 eslint 提到的错误之上,继续定义

const google = window.google;

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

如果您在 index.html 中包含 Google API 脚本,则有无需在 componentDidMount() 中 createElement。 你可以这样做-

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

将脚本添加到 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>
    </>
  );
};

如果在服务器端呈现必须检查是在浏览器环境中,因为 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,
    });
  };
}
...

在 React 应用中,

在 index.html 中使用脚本标签加载 google 地图 api 不工作,会给你错误 Access origin deny .....

解决方法是在下游模块系统中加载 google 映射 api,使用 useEffect() 挂钩。

例如,我简单地使用app.js加载api,你可以使用任何组件来这样做。不需要 app.js

这是我的工作代码:

                 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 (

不要忘记将你的 google 地图 api 键放在 .env 文件中, 所以你可以将其称为

              process.env.REACT_APP_GOOGLEMAPS_API_KEY

.env 文件应放在根文件夹中,与 package.json 所在的位置相同,因此 .env 文件应位于 package.json 文件旁边。

这是 .env 文件的样子:

              REACT_APP_GOOGLEMAPS_API_KEY=AIzajfU2J8m4vE 

记住,您的密钥必须以“REACT_APP_”开头,