首页 > 解决方案 > 使用 React 和 @googlemaps/js-api-loader 未显示 Google 地图标记

问题描述

我未能在 Gatsby 项目中向我的 Google 地图组件添加标记。我被特别要求不要使用任何第三方库,例如react-google-maps,所以请不要推荐这些。我要使用@googlemaps/js-api-loader.

我可以很好地加载地图,但我无法显示标记。它被创建为一个新的google.maps.Marker就好了,并且记录结果表明它正在正确接收lnglat。我已经尝试了各种各样的事情(承诺、回调、异步/等待、不同的范围等),但似乎在markerMaker之前完成mapMaker,即使我试图用作挂钩map的依赖项。useEffect

我试图将它存储map为一个状态,因为它正在返回一个承诺,但它仍然只是作为一个承诺返回,所以我现在很困惑。

下面的代码:

import React, { useState, useEffect } from "react"

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

const loader = new Loader({
  apiKey: "APIKEY",
  version: "weekly",
  // libraries: ["places"],
})
const mapOptions = {
  center: {
    lat: -27.4705,
    lng: 153.026,
  },
  zoom: 12,
}

const mapMaker = async () => {
  try {
    const google = await loader.load()
    const map = await new google.maps.Map(
      document.getElementById("map"),
      mapOptions
    )
    console.log("map loaded")
    return map
  } catch (error) {
    console.log(error)
  }
}

const markerMaker = async (pos, map) => {
  try {
    const google = await loader.load()
    const marker = new google.maps.Marker({
      position: pos,
      setMap: map,
      title: "test",
    })
    console.log("marker loaded")
  } catch (error) {
    console.log(error)
  }
}

const GoogleMap = ({ className, practices }) => {
  const [map, setMap] = useState({})

  useEffect(() => {
    setMap(mapMaker())
  }, [])

  useEffect(() => {
    markerMaker({ lat: -27.081149410091783, lng: 152.9497979199946 }, map)
  }, [map])

  return <div className={className} id="map"></div>
}

export default GoogleMap

任何见解将不胜感激。

标签: reactjsgoogle-maps

解决方案


鉴于没有工作示例,我将假设问题是标记在地图可用之前正在运行。

您运行的似乎有两个不正确的假设:

  1. useEffect(() => setMap(mapMaker(), [])将状态的值设置mapMaker为谷歌地图实例的返回值。
  2. 仅在声明第一点中的useEffect(fn, [maps])实例后才会运行。

首先,实际发生的是函数mapMaker是异步的,因此返回一个Pomise. 因此,您的代码实际上正在做的是将状态设置为Promise {<pending>}. 为了解决这个问题,您必须将代码更改为:

  useEffect(() => {
    mapMaker().then(map => setMap(map);
  }, [])

  // OR if you prefer async / await

  const loadMap = async () => {
    const map = await mapMaker();
    setMaps(map);
  }
  useEffect(() => {
    loadMap()
  }, [])

现在,由于第二点,仅此一项并不能解决问题。当您将依赖项传递给useEffect它时,它将在初始值以及值的每次更改上运行。

因此,您的代码可以markerMaker并行mapMaker有效地运行。然后markerMaker在您设置mapPromise {<pending>}第一个 useEffect 时运行第二次。

为了解决这个问题,您需要map在运行 markerMaker 之前检查是否已将其设置为谷歌地图的实例。

一个快速的解决办法是:

  const [map, setMap] = useState(null) // set initial state to null | undefined
  useEffect(() => {
    if (map !== null) { // check for the initial value
      markerMaker({ lat: -27.081149410091783, lng: 152.9497979199946 }, map)
    }
  }, [map])

你可以在沙盒中玩这个。


推荐阅读