Gatsby项目使用@googlemaps/js-api-loader时Google Maps标记无法显示问题
问题修复方案
核心问题梳理
- 异步返回值直接存入state:
mapMaker是异步函数,执行后返回Promise对象,直接执行setMap(mapMaker())会将Promise存入state,而非真实的地图实例,导致标记挂载时拿到的入参无效。 - Marker配置参数错误:Google Maps Marker构造函数的挂载属性为
map,你代码中误写为setMap(setMap是Marker实例的方法,不能作为构造参数传入),这是标记无法显示的直接原因。 - DOM节点获取不稳定:直接使用
document.getElementById在React渲染时序异常时可能无法获取到地图容器,推荐使用useRef绑定DOM节点更稳妥。
修正后可运行代码
import React, { useState, useEffect, useRef } from "react" import { Loader } from "@googlemaps/js-api-loader" const loader = new Loader({ apiKey: "APIKEY", version: "weekly", }) const mapOptions = { center: { lat: -27.4705, lng: 153.026, }, zoom: 12, } // 传入dom节点参数,避免全局查找dom const mapMaker = async (mapDom) => { try { const google = await loader.load() // google.maps.Map为同步构造,不需要加await const map = new google.maps.Map(mapDom, mapOptions) console.log("map loaded") return map } catch (error) { console.log(error) } } const markerMaker = async (pos, map) => { try { const google = await loader.load() // 构造参数将setMap改为map const marker = new google.maps.Marker({ position: pos, map: map, title: "test", }) console.log("marker loaded") return marker } catch (error) { console.log(error) } } const GoogleMap = ({ className, practices }) => { const mapRef = useRef(null) const [map, setMap] = useState(null) // 初始化地图 useEffect(() => { // 确保dom节点存在再初始化 if (!mapRef.current) return const init = async () => { const mapInstance = await mapMaker(mapRef.current) setMap(mapInstance) } init() }, []) // 地图实例初始化完成后再添加标记 useEffect(() => { if (!map) return markerMaker({ lat: -27.081149410091783, lng: 152.9497979199946 }, map) }, [map]) return <div className={className} ref={mapRef}></div> } export default GoogleMap
额外优化建议
- 不需要重复调用
loader.load(),API全局仅需加载一次,你可以把加载后的google对象存入state或者全局变量,避免重复加载逻辑。 - 如果后续需要添加多个标记,建议将标记列表存入state,监听标记列表变化批量更新标记,避免重复创建实例。
内容的提问来源于stack exchange,提问作者kmars
相关产品推荐
相关产品推荐

