Fix Leaflet map initialization: prevent DOM errors and ensure robust container checks

- Refactored initializeMap to accept the DOM node instead of the ref object
- Updated all checks to use the DOM node directly
- Improved useInitializeMap to only call initializeMap when the container is ready
- Prevents "mapRef.current ist nicht definiert oder nicht im DOM" errors
- Ensures map is only initialized when the container is attached
This commit is contained in:
ISA
2025-08-19 15:56:24 +02:00
parent db147543d9
commit bf4fc95b8e
8 changed files with 106 additions and 47 deletions

View File

@@ -5,48 +5,50 @@ import "leaflet/dist/leaflet.css";
import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
import "overlapping-marker-spiderfier-leaflet";
export const initializeMap = async (
mapRef,
setMap,
setOms,
export const initializeMap = (
mapContainer,
setMenuItemAdded,
addItemsToMapContextMenu,
hasRights,
setPolylineEventsDisabled
setPolylineEventsDisabled,
logError = false
) => {
const basePath = process.env.NEXT_PUBLIC_BASE_PATH;
if (!mapRef.current) {
console.error("❌ Fehler: mapRef.current ist nicht definiert.");
return;
if (
!mapContainer ||
!(mapContainer instanceof HTMLElement) ||
!document.body.contains(mapContainer)
) {
if (logError) {
console.error("❌ Fehler: map container ist nicht definiert oder nicht im DOM.");
}
return null;
}
// Robuste Entfernung einer evtl. alten Leaflet-Instanz und Reset des DOM-Elements
if (mapRef.current) {
if (mapRef.current._leaflet_id) {
if (mapContainer) {
if (mapContainer._leaflet_id) {
try {
// Leaflet-Instanz entfernen
if (
mapRef.current._leaflet_map &&
typeof mapRef.current._leaflet_map.remove === "function"
) {
mapRef.current._leaflet_map.remove();
if (mapContainer._leaflet_map && typeof mapContainer._leaflet_map.remove === "function") {
mapContainer._leaflet_map.remove();
}
// Leaflet 1.7+ speichert die Map-Instanz in L.Map._instances
if (L && L.Map && L.Map._instances && mapRef.current._leaflet_id) {
delete L.Map._instances[mapRef.current._leaflet_id];
if (L && L.Map && L.Map._instances && mapContainer._leaflet_id) {
delete L.Map._instances[mapContainer._leaflet_id];
}
// Auch in L.DomUtil._store ggf. entfernen
if (L && L.DomUtil && L.DomUtil._store && mapRef.current._leaflet_id) {
delete L.DomUtil._store[mapRef.current._leaflet_id];
if (L && L.DomUtil && L.DomUtil._store && mapContainer._leaflet_id) {
delete L.DomUtil._store[mapContainer._leaflet_id];
}
// _leaflet_id vom DOM-Element entfernen
delete mapRef.current._leaflet_id;
delete mapContainer._leaflet_id;
// Alle weiteren _leaflet-Properties entfernen
for (const key in mapRef.current) {
for (const key in mapContainer) {
if (key.startsWith("_leaflet")) {
try {
delete mapRef.current[key];
delete mapContainer[key];
} catch (e) {}
}
}
@@ -55,22 +57,24 @@ export const initializeMap = async (
}
}
// Container leeren (immer, auch wenn keine Map-Instanz)
mapRef.current.innerHTML = "";
mapContainer.innerHTML = "";
}
const url = new URL(window.location.origin);
let tileLayerUrl = "";
let tileLayerUrl = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
try {
if (window && window.__tileSource) {
tileLayerUrl = window.__tileSource;
} else {
const res = await fetch("/config.json");
const config = await res.json();
if (config.tileSources && config.active && config.tileSources[config.active]) {
window.__tileSource = config.tileSources[config.active];
tileLayerUrl = window.__tileSource;
// Optional: Map reload oder Layer neu setzen, falls gewünscht
// Synchronous config fetch using XMLHttpRequest (since fetch is async)
const xhr = new XMLHttpRequest();
xhr.open("GET", "/config.json", false); // false = synchronous
xhr.send(null);
if (xhr.status === 200) {
const config = JSON.parse(xhr.responseText);
if (config.tileSources && config.active && config.tileSources[config.active]) {
window.__tileSource = config.tileSources[config.active];
tileLayerUrl = window.__tileSource;
}
}
}
} catch (e) {
@@ -79,7 +83,7 @@ export const initializeMap = async (
let initMap;
try {
initMap = L.map(mapRef.current, {
initMap = L.map(mapContainer, {
center: [53.111111, 8.4625],
zoom: 12,
minZoom: 5,
@@ -114,10 +118,8 @@ export const initializeMap = async (
nearbyDistance: 20,
});
setMap(initMap);
setOms(overlappingMarkerSpiderfier);
if (typeof addItemsToMapContextMenu === "function") {
addItemsToMapContextMenu(initMap, setMenuItemAdded, setPolylineEventsDisabled);
}
return { map: initMap, oms: overlappingMarkerSpiderfier };
};