I'm using React with TypeScript and { MarkerClusterer } from "@googlemaps/markerclusterer to have Clusters in my map, but my problem is that the first time I render the Google Map, the Clusters are not showing, but if I re-render the view, the Clusters appear (f5).
I tried using console.log() to see if the options I send to the Clusters are sent properly, and yes they are, so I think that the problem could be in the Google library
This is my Cluster component:
import React from "react";
import { Countryside } from "../../shared/types";
import Point from "../../assets/icons/svg/EstablishmentsMapPage/point.svg";
import { MarkerClusterer } from "@googlemaps/markerclusterer";
interface ClusterProps {
markers: Countryside[];
isVisible: boolean;
map?: google.maps.Map;
onClick?: (...args: any) => Promise<void>;
}
const Cluster: React.FC<ClusterProps> = ({
markers,
onClick,
map,
isVisible,
}) => {
const [clusters, setClusters] = React.useState<MarkerClusterer>();
const [markersForCluster, setMarkersForCluster] =
React.useState<google.maps.Marker[]>();
React.useEffect(() => {
if (!clusters) {
const newMarkers = markers.map((value, i) => {
console.log("value", value)
const marker: any = new google.maps.Marker({
position: {
lat:
value.countryside_lat != undefined
? parseFloat(value.countryside_lat)
: parseFloat(value.countryside_lat),
lng:
value.countryside_lon != undefined
? parseFloat(value.countryside_lon)
: parseFloat(value.countryside_lon),
},
visible: isVisible,
icon: Point,
zIndex: Number(google.maps.Marker.MAX_ZINDEX) + i,
label: {
className: "map-marker",
color: "#33333",
fontFamily: "'Poppins', sans-serif",
fontWeight: "600",
fontSize: "1.2rem",
text: "" + value.count_silobags,
},
});
const infoWindow = new google.maps.InfoWindow({
content: `
<div style="background-color: #ffffff;
border-radius: 8px;
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
padding: 5px;
font-family: 'Poppins', sans-serif;">
<h3 style="font-size: 18px;
font-weight: bold;
color: #333333;
margin-bottom: 8px;">${value.countryside_name}</h3>
</div>
`,
});
if (infoWindow) {
marker.addListener("mouseover", () => {
infoWindow.open({ anchor: marker, map, shouldFocus: false });
});
marker.addListener("mouseout", () => {
infoWindow.close();
});
}
return marker;
});
if (newMarkers.length === 0) return;
setMarkersForCluster(newMarkers);
setClusters(
new MarkerClusterer({
markers: newMarkers,
map,
renderer: {
render: ({ count, position, markers }) => {
const finalCount: any =
markers && markers.length > 0
? [...markers]
.map((val: any) => {
return val.getLabel()?.text;
})
.reduce(
(partialSum: any, a: any) => partialSum + parseInt(a),
0
)
: 0;
return new google.maps.Marker({
label: {
text: String(finalCount),
className: "map-marker",
color: "#33333",
fontFamily: "'Poppins', sans-serif",
fontWeight: "600",
fontSize: "1.2rem",
},
position: {
lat: position.lat(),
lng: position.lng(),
},
visible: isVisible,
map,
icon: Point,
zIndex: Number(google.maps.Marker.MAX_ZINDEX) + count,
});
},
},
})
);
}
return () => {
if (clusters) {
markersForCluster?.map((value) => value.setMap(null));
clusters.clearMarkers();
setClusters(undefined);
}
};
}, [clusters, markers, isVisible]);
React.useEffect(() => {
if (map && markers && markersForCluster) {
google.maps.event.clearListeners(map, "onClick");
markersForCluster.forEach((value, i) => {
value.setVisible(isVisible);
if (onClick) {
value.addListener("click", async () => {
const currentZoom = map.getZoom();
await onClick(markers[i].countryside_id);
map.panTo(value.getPosition() as google.maps.LatLng);
if (currentZoom && currentZoom < 12) map.setZoom(12);
});
}
});
}
}, [clusters, onClick, isVisible]);
return null;
};
export default Cluster;