如何在@googlemaps/react-wrapper中使用MarkerClusterer并解决聚类不显示问题
解决@googlemaps/react-wrapper中MarkerClusterer不显示的问题
问题分析
你的代码存在以下核心问题导致聚类功能失效:
- MarkerClusterer初始化时传入了DOM元素的
ref,而非谷歌地图的map实例 - 标记和聚类的创建逻辑未等待地图实例完全初始化完成
- 未正确关联地图实例与标记、聚类组件
修复步骤
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
相关产品推荐
相关产品推荐

