diff --git a/frontend/src/components/Map/LocalitiesMap.tsx b/frontend/src/components/Map/LocalitiesMap.tsx index 8a50c5058..cf2e3427f 100755 --- a/frontend/src/components/Map/LocalitiesMap.tsx +++ b/frontend/src/components/Map/LocalitiesMap.tsx @@ -1,7 +1,6 @@ import { useGetLocalityDetailsQuery } from '../../redux/localityReducer' import { useState, useEffect, useRef } from 'react' import 'leaflet/dist/leaflet.css' -import { countryPolygons } from '../../country_data/countryPolygons.ts' import L, { LatLngExpression } from 'leaflet' import { SimplifiedLocality } from '../../shared/types/data.js' import { skipToken } from '@reduxjs/toolkit/query' @@ -25,6 +24,7 @@ export const LocalitiesMap = ({ localities, isFetching }: Props) => { const [selectedLocality, setSelectedLocality] = useState(null) const mapRef = useRef(null) const [map, setMap] = useState(null) + const borderLayerRef = useRef(null) const [isOpen, setIsOpen] = useState(false) const [localityDetailsIsOpen, setLocalityDetailsIsOpen] = useState(false) const [clusteringEnabled, setClusteringEnabled] = useState(true) @@ -34,6 +34,26 @@ export const LocalitiesMap = ({ localities, isFetching }: Props) => { selectedLocality ?? skipToken ) + // Lazy load country polygons to avoid blocking the main thread with 4.4MB of data + const [countryPolygons, setCountryPolygons] = useState(null) + + useEffect(() => { + let mounted = true + + // Dynamically import country polygons to avoid blocking on initial load + void import('../../country_data/countryPolygons.ts') + .then(module => { + if (mounted) setCountryPolygons(module.countryPolygons) + }) + .catch(() => { + if (mounted) setCountryPolygons([]) + }) + + return () => { + mounted = false + } + }, []) + useEffect(() => { if (!mapRef.current) return @@ -57,21 +77,9 @@ export const LocalitiesMap = ({ localities, isFetching }: Props) => { noWrap: true, }) - // ---- Layers on top of base maps ---- - // Create a polygon layer for the country borders that is in layer control panel. const borderLayer = L.layerGroup() - countryPolygons.forEach(countryBorder => { - L.polygon(countryBorder as LatLngExpression[], { color: 'gray', weight: 1 }).addTo(mapInstance) - - const polygon = L.polygon(countryBorder as LatLngExpression[], { - color: '#136f94', - fillOpacity: 0.3, - weight: 1, - }) - borderLayer.addLayer(polygon) - }) - + borderLayerRef.current = borderLayer const baseMaps = { OpenTopoMap: topomap, OpenStreetMap: osm, @@ -97,10 +105,26 @@ export const LocalitiesMap = ({ localities, isFetching }: Props) => { northArrow.addTo(mapInstance) return () => { + borderLayerRef.current = null mapInstance.remove() } }, []) + useEffect(() => { + if (!map || !countryPolygons || !borderLayerRef.current) return + + borderLayerRef.current.clearLayers() + + countryPolygons.forEach(countryBorder => { + const polygon = L.polygon(countryBorder as LatLngExpression[], { + color: '#136f94', + fillOpacity: 0.3, + weight: 1, + }) + borderLayerRef.current?.addLayer(polygon) + }) + }, [countryPolygons, map]) + useEffect(() => { if (!map || isFetching) return