I have this code for Leaflet map where the popup content of markers is dynamically created for every unique profile ID.Markers are creating from data which arrives from WebSocket. However, each time new data arrives, the popup is being re-rendered. How can I prevent the popup from re-rendering?
const DashboardMap: React.FC = () => {
const [socket, setSocket] = useState<WebSocket | null>(null);
const [isConnected, setIsConnected] = useState(false);
const [dataMap, setDataMap] = useState<Record<string, SummaryMapData>>({});
const [localTotalActivities, setLocalTotalActivities] = useState<Record<string, number>>({});
const [summaryMapData, setSummaryMapData] = useState<SummaryMapData | null>(null);
const [selectedActivities, setSelectedActivities] = useState<string[]>(['mdmResponse', 'ecrResponse', 'eventHeartBeat', 'eventTransaction', 'eventLog', 'eventSystem', 'logOn']);
newSocket.onmessage = (event) => {
const data = JSON.parse(event.data) as SummaryMapData;
setSummaryMapData(data);
console.log(data);
};
const updateDataMap = (summaryMapData: SummaryMapData) => {
if (summaryMapData?.hasOwnProperty('profileId')) {
const profileId = summaryMapData.profileId;
setDataMap(prevDataMap => {
const prevProfileData = prevDataMap[profileId] || {
type: "",
profileId: "",
bank: "",
merchant: "",
timestamp: "",
init: 0,
mdmResponse: 0,
ecrResponse: 0,
eventHeartBeat: 0,
eventTransaction: 0,
eventLog: 0,
eventSystem: 0,
logOn: 0,
latitude: 0,
longitude: 0,
totalActivities: 0,
};
const newTotalActivities = (prevProfileData.totalActivities || 0) + 1;
setLocalTotalActivities(prevLocalTotalActivities => ({
...prevLocalTotalActivities,
[profileId]: newTotalActivities,
}));
return {
...prevDataMap,
[profileId]: {
...prevProfileData,
...summaryMapData,
timestamp: prevProfileData.timestamp > summaryMapData.timestamp ? prevProfileData.timestamp : summaryMapData.timestamp,
totalActivities: newTotalActivities,
init: prevProfileData.init + (summaryMapData.init || 0),
mdmResponse: prevProfileData.mdmResponse + (summaryMapData.mdmResponse || 0),
ecrResponse: prevProfileData.ecrResponse + (summaryMapData.ecrResponse || 0),
eventHeartBeat: prevProfileData.eventHeartBeat + (summaryMapData.eventHeartBeat || 0),
eventTransaction: prevProfileData.eventTransaction + (summaryMapData.eventTransaction || 0),
eventLog: prevProfileData.eventLog + (summaryMapData.eventLog || 0),
eventSystem: prevProfileData.eventSystem + (summaryMapData.eventSystem || 0),
logOn: prevProfileData.logOn + (summaryMapData.logOn || 0),
},
};
});
}
};
useEffect(() => {
if (summaryMapData) {
updateDataMap(summaryMapData);
}
}, [summaryMapData]);
<MapContainer center={[42.6507, 18.0944]} zoom={5} fullscreenControl={true} style={{height: "300px"}}>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
map = useMap();
<MarkerClusterGroup>
{filteredMarkers.map(([profileId, data], index) => (
<Marker
key={profileId}
position={[data.latitude, data.longitude]}
icon={customIcon}
>
<Popup key={profileId}>
<div>
<strong>Profile ID:</strong> {data.profileId} <br/>
<strong>Bank:</strong> {data.bank || 'N/A'} <br/>
<strong>Time ago:</strong> {getTimeAgoString(data.timestamp)} <br/>
<strong>Merchant:</strong> {data.merchant || 'N/A'} <br/>
<strong>Inits:</strong> {data.init || 0} <br/>
<strong>Mdm events:</strong> {data.mdmResponse || 0} <br/>
<strong>Ecr events:</strong> {data.ecrResponse || 0} <br/>
<strong>Heartbeats:</strong> {data.eventHeartBeat || 0} <br/>
<strong>Transactions:</strong> {data.eventTransaction || 0} <br/>
<strong>Logs:</strong> {data.eventLog || 0} <br/>
<strong>System events:</strong> {data.eventSystem || 0} <br/>
<strong>Logons:</strong> {data.logOn || 0} <br/>
<strong>Total Activities:</strong> {localTotalActivities[data.profileId] || 0}
<br/>
</div>
</Popup>
{index === 0 && <RecenterAutomatically lat={data.latitude} lng={data.longitude} zoom={5}/>}
</Marker>
))}
</MarkerClusterGroup>
</MapContainer>
I have attempted to use useMemo and other techniques, but I haven't been able to prevent the popup from re-rendering every time new data arrives. My goal is for the popup to update only the fields that have changed, rather than re-rendering entirely