如何仅在需要时才在我的 React 应用程序中加载 google maps api <script>?

IT技术 javascript google-maps reactjs
2021-05-10 12:27:48

我想尝试使用谷歌地图 API 来显示地图,但我想知道是否有<script>比将它放入 index.html更好的加载标签的方法

我希望脚本仅在我去/map路线时加载所以,我想从我的中删除它index.html并动态加载它。但是,我还想确保如果它已经被加载,我不会尝试再次加载它。

我不确定是否有图书馆来处理这个问题。到目前为止我尝试过的(但失败了)是创建一个loadScript函数,函数将 a 附加<script>到实际的 dom 并为其分配一个键,因此在这种情况下'google-maps.

谢谢

4个回答

2019 年 10 月 6 日更新:示例代码仍然运行良好,我刚刚将它们更新为使用非装饰器语法。


这就是我让它在我最近的项目中工作的原因。我使用了react-async-script-loader组件。

import React from 'react';
import scriptLoader from 'react-async-script-loader';

class Maps extends React.Component {
  constructor(props) {
    super(props);
    this.map = null;
  }

  componentWillReceiveProps({ isScriptLoaded, isScriptLoadSucceed }) {
    if (isScriptLoaded && !this.props.isScriptLoaded) {
      // load finished
      if (isScriptLoadSucceed) {
        this.map = new google.maps.Map(this.refs.map, {
          center: { lat: 10.794234, lng: 106.706541 },
          zoom: 20
        });

        if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition(
            position => {
              const pos = {
                lat: position.coords.latitude,
                lng: position.coords.longitude
              };

              this.map.setCenter(pos);

              const marker = new google.maps.Marker({
                position: pos,
                map: this.map,
                title: 'Hello World!'
              });
            },
            () => {
              console.log('navigator disabled');
            }
          );
        } else {
          // Browser doesn't support Geolocation
          console.log('navigator disabled');
        }
      } else this.props.onError();
    }
  }

  render() {
    return (
      <div>
        <div ref="map" style={{ height: '80%', width: '100%' }}></div>
        {!this.map && <div className="center-md">Loading...</div>}
      </div>
    );
  }
}

export default scriptLoader(['https://maps.googleapis.com/maps/api/js?key=API_KEY'])(Maps);

谢谢阮成就像google现在在全局范围内我使用window.google.

import React, { Component } from 'react';
import scriptLoader from 'react-async-script-loader';
class Map extends Component{
    constructor(props) {
        super(props);
    }
    componentWillReceiveProps({isScriptLoadSucceed}){
        if (isScriptLoadSucceed) {
            var markers = [];

            var map = new window.google.maps.Map(document.getElementById('map'), {
                zoom: 12,
                center: {lat: 37.7749300, lng: -122.4194200}
            });
        }
        else{
            alert("script not loaded")
        }
    }

    render(){
        return(
            <div>
                <div id="map" style={{height: "600px"}}></div>
            </div>
        )
    }
}

export default scriptLoader(
    ["https://maps.googleapis.com/maps/api/js?key= APIKEY"]
)(Map)

使用 react hook 我们还可以加载外部脚本

https://usehooks.com/useScript/

//useScript custom hooks from the site

let cachedScripts = [];

function useScript(src) {
  // Keeping track of script loaded and error state

  const [state, setState] = useState({
    loaded: false,
    error: false
  });

  useEffect(
    () => {
      // If cachedScripts array already includes src that means another instance ...
      // ... of this hook already loaded this script, so no need to load again.
      if (cachedScripts.includes(src)) {
        setState({
          loaded: true,

          error: false
        });
      } else {
        cachedScripts.push(src);
        // Create script
        let script = document.createElement("script");
        script.src = src;
        script.async = true;
        // Script event listener callbacks for load and error
        const onScriptLoad = () => {
          setState({
            loaded: true,
            error: false
          });
        };

        const onScriptError = () => {
          // Remove from cachedScripts we can try loading again
          const index = cachedScripts.indexOf(src);
          if (index >= 0) cachedScripts.splice(index, 1);
          script.remove();
          setState({
            loaded: true,
            error: true
          });
        };
        script.addEventListener("load", onScriptLoad);
        script.addEventListener("error", onScriptError);
        // Add script to document body
        document.body.appendChild(script);
        // Remove event listeners on cleanup
        return () => {
          script.removeEventListener("load", onScriptLoad);
          script.removeEventListener("error", onScriptError);
        };
      }
    },
    [src] // Only re-run effect if script src changes
  );
  return [state.loaded, state.error];
}


用法

//App.js
import React from "react";
import ReactDOM from "react-dom";
import { useState, useEffect } from "react";
function App() {
  const [loaded, error] = useScript(
    "https://maps.googleapis.com/maps/api/js?key=API_KEY"
  );
  useEffect(() => {
    if (loaded) {
      new window.google.maps.Map(document.getElementById("map"), {
        zoom: 12,
        center: { lat: 37.77493, lng: -122.41942 }
      });
    }
  }, [loaded]);

  return (
    <div>
      <div>
        Script loaded: <b>{loaded.toString()}</b>
      </div>
      <div id="map" style={{ height: "600px" }} />
    </div>
  );
}

另一个用于加载 Google 地图库的react-dependent-script,它提供了以下功能:

  • 确保首先加载 JavaScript 和/或 CSS,然后呈现您的内容
  • 确保外部内容只加载一次,无论 render() 函数被调用多少次

这是一个简单的示例,您将地图组件包装ReactDependentScript组件中:

<ReactDependentScript
      scripts={[
        "https://maps.googleapis.com/maps/api/js?key={YOUR-KEY-GOES-HERE}"
      ]}>
      <Map center={{ lat: -34.397, lng: 150.644 }} zoom={3} />
</ReactDependentScript>

这是一个演示 供您参考

截至2021 年 4 月, Google 已“在现代 Web 应用程序中更轻松地使用 Maps JavaScript API ”,在其博客文章中提供了更多详细信息:在现代 Web 应用程序中加载 Google Maps Platform JavaScript

这是Google Maps JavaScript API Loader 库的说明

import { Loader } from '@googlemaps/js-api-loader';

const loader = new Loader({
  apiKey: "",
  version: "weekly",
  libraries: ["places"]
});

const mapOptions = {
  center: {
    lat: 0,
    lng: 0
  },
  zoom: 4
};

// Promise
loader
  .load()
  .then((google) => {
    new google.maps.Map(document.getElementById("map"), mapOptions);
  })
  .catch(e => {
    // do something
  });

或者,如果需要,您可以使用Google Maps JavaScript API React Wrapper 库