You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在@googlemaps/react-wrapper中使用MarkerClusterer并解决聚类不显示问题

解决@googlemaps/react-wrapper中MarkerClusterer不显示的问题

问题分析

你的代码存在以下核心问题导致聚类功能失效:

  1. MarkerClusterer初始化时传入了DOM元素的ref,而非谷歌地图的map实例
  2. 标记和聚类的创建逻辑未等待地图实例完全初始化完成
  3. 未正确关联地图实例与标记、聚类组件

修复步骤

1. 等待地图实例就绪后处理标记和聚类

将标记创建和聚类初始化逻辑放在map状态更新后的回调中,确保地图实例已完全创建。

2. 修正MarkerClusterer的初始化参数

@googlemaps/markerclusterer构造函数需要接收map实例作为参数,而非DOM的ref,正确参数结构为{ map, markers }。

3. 移除标记的手动map关联

MarkerClusterer会自动将标记添加到地图上,无需在创建Marker时指定map属性。

修改后的完整App.js代码

/*global google*/
import { useState, useEffect, useRef } from "react";
import { Wrapper } from "@googlemaps/react-wrapper";
import { MarkerClusterer } from "@googlemaps/markerclusterer";
import { createCustomEqual } from "fast-equals";

const markerList = [
  { id: "A12345", uuid: "500924cf83424aad9e7d386bbec88ef6", lat: 44.459744, lng: -73.214126, assetName: "A" },
  { id: "B09423", uuid: "500924cf83424aad9e7d386bbec88ef6", lat: 44.465291, lng: -73.190723, assetName: "A" },
  { id: "C98765", uuid: "c0385833-e483-40d1-803f-2b4c26ae3799", lat: 44.476949, lng: -73.210578, assetName: "B" },
  { id: "D99999", uuid: "c0385833-e483-40d1-803f-2b4c26ae3799", lat: 44.444572, lng: -73.208741, assetName: "B" },
  { id: "E12345", uuid: "500924cf83424aad9e7d386bbec88ef6", lat: 38.459744, lng: -81.214126, assetName: "A" },
  { id: "F09423", uuid: "500924cf83424aad9e7d386bbec88ef6", lat: 38.465291, lng: -81.190723, assetName: "A" },
  { id: "G98765", uuid: "c0385833-e483-40d1-803f-2b4c26ae3799", lat: 38.476949, lng: -81.210578, assetName: "B" },
  { id: "H99999", uuid: "c0385833-e483-40d1-803f-2b4c26ae3799", lat: 38.444572, lng: -81.208741, assetName: "B" },
]

const render = (status) => {
  return <h1>{status}</h1>;
};

const App = () => {
  const [zoom, setZoom] = useState(8); // initial zoom
  const [center, setCenter] = useState({ lat: 44.45, lng: -73.21 });

  const onIdle = (m) => {
    console.log("onIdle");
  };

  return (
    <>
      <div style={{ width: "500px", height: "500px" }}>
        <Wrapper
          apiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}
          render={render}
        >
          <Map
            center={center}
            onIdle={onIdle}
            zoom={zoom}
            style={{ flexGrow: "1", height: "100%" }}
          />
        </Wrapper>
      </div>
    </>

  );
};

const Map = ({ onIdle, children, style, ...options }) => {
  const ref = useRef(null);
  const [map, setMap] = useState();
  const clustererRef = useRef(null);

  useEffect(() => {
    if (ref.current && !map) {
      const newMap = new window.google.maps.Map(ref.current, {});
      setMap(newMap);
    }
  }, [ref, map]);

  useEffect(() => {
    if (!map) return;

    // 创建标记
    const markers = markerList.map((m) => {
      return new window.google.maps.Marker({
        position: { lat: parseFloat(m.lat), lng: parseFloat(m.lng) }
      });
    });

    // 初始化聚类器
    if (!clustererRef.current) {
      clustererRef.current = new MarkerClusterer({ map, markers });
    }

    // 清理函数:防止内存泄漏
    return () => {
      markers.forEach(marker => marker.setMap(null));
      if (clustererRef.current) {
        clustererRef.current.clearMarkers();
        clustererRef.current = null;
      }
    };
  }, [map]);

  useDeepCompareEffectForMaps(() => {
    if (map) {
      map.setOptions(options);
    }
  }, [map, options]);

  useEffect(() => {
    if (map) {
      ["click", "idle"].forEach((eventName) =>
        google.maps.event.clearListeners(map, eventName)
      );

      if (onIdle) {
        map.addListener("idle", () => onIdle(map));
      }
    }
  }, [map, onIdle]);

  return (
    <>
      <div ref={ref} style={style} />
    </>
  );
};

const deepCompareEqualsForMaps = createCustomEqual((deepEqual) => (a, b) => {
  if (a instanceof google.maps.LatLng || b instanceof google.maps.LatLng) {
    return new google.maps.LatLng(a).equals(new google.maps.LatLng(b));
  }
  return deepEqual(a, b);
});

function useDeepCompareMemoize(value) {
  const ref = useRef();

  if (!deepCompareEqualsForMaps(value, ref.current)) {
    ref.current = value;
  }
  return ref.current;
}

function useDeepCompareEffectForMaps(callback, dependencies) {
  useEffect(callback, dependencies.map(useDeepCompareMemoize));
}

export default App;

内容的提问来源于stack exchange,提问作者Jean-Baptiste Bolh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 19:30:41