Using cluster with AdvancedMarker + InfoWindow #325
-
Hi!
Can anyone please help me? Below is example code Mapimport AdvancedMarkerElement = google.maps.marker.AdvancedMarkerElement;
import { Map, useMap } from '@vis.gl/react-google-maps';
import { MarkerClusterer } from '@googlemaps/markerclusterer';
const map = useMap();
const [selectedInstitution, setSelectedInstitution] = useState<number | null>(null);
const [markers, setMarkers] = useState<{ [key: string]: AdvancedMarkerElement }>({});
const clusterer = useRef<MarkerClusterer | null>(null);
const polandBounds = {
east: 26.5,
west: 11.5,
north: 56.5,
south: 47,
};
useEffect(() => {
if (!map) return;
if (!clusterer.current) {
clusterer.current = new MarkerClusterer({ map });
}
}, [map]);
useEffect(() => {
clusterer.current?.clearMarkers();
clusterer.current?.addMarkers(Object.values(markers));
}, [markers]);
const setMarkerRef = (marker: AdvancedMarkerElement | null, key: string): void => {
if (marker && markers[key]) return;
if (!marker && !markers[key]) return;
setMarkers((prev) => {
if (marker) {
return { ...prev, [key]: marker };
} else {
const newMarkers = { ...prev };
delete newMarkers[key];
return newMarkers;
}
});
};
<Map
mapId={XXX}
style={{
width: '100%',
height: heightParsed,
}}
fullscreenControl={false}
streetViewControl={false}
mapTypeControl={false}
clickableIcons={false}
restriction={{
latLngBounds: polandBounds,
strictBounds: true,
}}
defaultBounds={polandBounds}
>
{places.map((p) => (
<GoogleMapsMarker
key={p.id}
setMarkerRef={(marker, key) => setMarkerRef(marker, key)}
selectedInstitution={selectedInstitution}
handleSetInstitution={(id) => setSelectedInstitution(id)}
/>
))}
</Map> Markerimport React, { useRef } from 'react';
import { AdvancedMarker, InfoWindow } from '@vis.gl/react-google-maps';
import AdvancedMarkerElement = google.maps.marker.AdvancedMarkerElement;
interface Props {
place: InstitutionSearch;
selectedInstitution: number | null;
setMarkerRef: (marker: AdvancedMarkerElement | null, id: string) => void;
}
export const GoogleMapsMarker = ({
place,
selectedInstitution,
setMarkerRef,
}: Props): JSX.Element => {
const ref = useRef<AdvancedMarkerElement | null>(null);
return (
<>
<AdvancedMarker
ref={(marker) => {
ref.current = marker;
setMarkerRef(marker, place.id.toString());
}}
onClick={() => {
console.log("Click");
}}
position={{
lat: place.geolocation.latitude,
lng: place.geolocation.longitude,
}}
>
ex.image
</AdvancedMarker>
{selectedInstitution === place.id && (
<InfoWindow
anchor={ref.current}
onCloseClick={() => handleSetInstitution(null)}
position={{
lat: place.geolocation.latitude + 0.001,
lng: place.geolocation.longitude,
}}
minWidth={270}
>
<div>POPUP DATA</div>
</InfoWindow>
)}
</>
);
}; only for place you need to create dummy interface/data :| |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 15 replies
-
I have yet to figure out exactly what is happening, but I was able to reproduce it. The problem seems to have something to do with unneeded re-rendering of the AdvancedMarker components due to the callbacks. Try replacing return (
<>
{places.map(p => (
<GoogleMapsMarker
key={p.id}
place={p}
setMarkerRef={(marker, key) => setMarkerRef(marker, key)}
/>
))}
</>
); with something like const markers = useMemo(
() =>
places.map((p) => (
<GoogleMapsMarker
key={p.id}
place={p}
setMarkerRef={(marker, key) => setMarkerRef(marker, key)}
/>
)),
[places]
);
return <>{markers}</> In my example that was already able to fix the problem. I'm still looking into what is going on under the hood, but I suspect we're triggering some sort of race-condition in the google maps API with the repeated updates of the markers. The marker to infowindow-connection looks alright as it is. |
Beta Was this translation helpful? Give feedback.
The thing is, that isn't officially supported. The content element is the topmost dom-element we have access to.
As per https://visgl.github.io/react-google-maps/docs/api-reference/components/info-window, I'd recommend using the AdvancedMarker component instead of InfoWindow if you need more flexibility in styling (I'm reworking the AdvancedMarker implementation and docs right now).