fix: Behebt TypeError: Cannot read properties of null (reading 'contextmenu') mit Redux
- Implementiert `store.subscribe()` in `setupPolylines.js`, um das Kontextmenü-Handling über Redux zu steuern. - Ersetzt `useDispatch()` und `useSelector()` durch `store.dispatch()` und `store.getState()` in einer Nicht-React-Datei. - Fügt eine `forceClose`-Action in `polylineContextMenuSlice.js` hinzu, um das Kontextmenü synchron mit `setInterval` zu schließen. - Stellt sicher, dass das Kontextmenü **immer vor Ablauf des 20-Sekunden-Intervalls** geschlossen wird. - Verhindert doppelte Menüinstanzen und sorgt für ein stabiles Verhalten bei wiederholten Interaktionen. ✅ Fix für `TypeError: Cannot read properties of null (reading 'contextmenu')` ✅ **Verhindert Kontextmenü-Fehler beim automatischen Datenupdate** ✅ **Redux-gesteuerte Menüverwaltung für stabilere Performance** ✅ **Kein unerwartetes Offenbleiben oder erneutes Rendern des Menüs mehr**
This commit is contained in:
@@ -79,10 +79,15 @@ import ShowAddStationPopup from "../AddPOIModal.js";
|
||||
import { useInitGisStationsStatic } from "../mainComponent/hooks/useInitGisStationsStatic";
|
||||
import { closeAddPoiModal } from "../../redux/slices/addPoiOnPolylineSlice.js";
|
||||
import AddPOIOnPolyline from "../AddPOIOnPolyline";
|
||||
import { closePolylineContextMenu } from "../../redux/slices/polylineContextMenuSlice";
|
||||
import { forceCloseContextMenu } from "../../redux/slices/polylineContextMenuSlice";
|
||||
|
||||
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
|
||||
const dispatch = useDispatch();
|
||||
const isPolylineContextMenuOpen = useSelector((state) => state.polylineContextMenu.isOpen);
|
||||
const contextMenuState = useSelector((state) => state.polylineContextMenu);
|
||||
|
||||
const polylinePosition = contextMenuState.position ? L.latLng(contextMenuState.position.lat, contextMenuState.position.lng) : null;
|
||||
const currentPoi = useSelector(selectCurrentPoi);
|
||||
//const setCurrentPoi = useSetRecoilState(currentPoiState);
|
||||
const polylineVisible = useSelector(selectPolylineVisible);
|
||||
@@ -876,6 +881,13 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
|
||||
console.log("🔥 Automatischer Klick-Event ausgelöst, um Spiderfy zu aktualisieren.");
|
||||
map.fire("click");
|
||||
}
|
||||
if (isPolylineContextMenuOpen) {
|
||||
dispatch(closePolylineContextMenu()); // Schließe das Kontextmenü, bevor das nächste Update passiert
|
||||
}
|
||||
if (map) {
|
||||
console.log("🔥 nochmal klick.");
|
||||
map.fire("click");
|
||||
}
|
||||
}, 20000);
|
||||
|
||||
// Aufräumen bei Komponentenentladung
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// /config/appVersion
|
||||
export const APP_VERSION = "1.1.41";
|
||||
export const APP_VERSION = "1.1.42";
|
||||
|
||||
32
redux/slices/polylineContextMenuSlice.js
Normal file
32
redux/slices/polylineContextMenuSlice.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// redux/slices/polylineContextMenuSlice.js
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
isOpen: false,
|
||||
position: null, // Serialisierbarer Wert { lat, lng }
|
||||
forceClose: false, // Neuer State, um das Schließen zu erzwingen
|
||||
};
|
||||
|
||||
const polylineContextMenuSlice = createSlice({
|
||||
name: "polylineContextMenu",
|
||||
initialState,
|
||||
reducers: {
|
||||
openPolylineContextMenu: (state, action) => {
|
||||
state.isOpen = true;
|
||||
state.position = { lat: action.payload.position.lat, lng: action.payload.position.lng };
|
||||
state.forceClose = false; // Beim Öffnen zurücksetzen
|
||||
},
|
||||
closePolylineContextMenu: (state) => {
|
||||
state.isOpen = false;
|
||||
state.position = null;
|
||||
},
|
||||
forceCloseContextMenu: (state) => {
|
||||
state.isOpen = false;
|
||||
state.position = null;
|
||||
state.forceClose = true; // Setzt Flagge, um Schließen zu signalisieren
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { openPolylineContextMenu, closePolylineContextMenu, forceCloseContextMenu } = polylineContextMenuSlice.actions;
|
||||
export default polylineContextMenuSlice.reducer;
|
||||
@@ -11,6 +11,7 @@ import gisSystemStaticReducer from "./slices/webService/gisSystemStaticSlice";
|
||||
import gisStationsStaticReducer from "./slices/webService/gisStationsStaticSlice";
|
||||
import poiTypesReducer from "./slices/db/poiTypesSlice";
|
||||
import addPoiOnPolylineReducer from "./slices/addPoiOnPolylineSlice";
|
||||
import polylineContextMenuReducer from "./slices/polylineContextMenuSlice";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -25,5 +26,6 @@ export const store = configureStore({
|
||||
gisStationsStatic: gisStationsStaticReducer,
|
||||
poiTypes: poiTypesReducer,
|
||||
addPoiOnPolyline: addPoiOnPolylineReducer,
|
||||
polylineContextMenu: polylineContextMenuReducer,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ import { polylineLayerVisibleState } from "../redux/slices/polylineLayerVisibleS
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { store } from "../redux/store"; // Importiere den Store
|
||||
import { openAddPoiOnPolylineModal } from "../redux/slices/addPoiOnPolylineSlice";
|
||||
import { openPolylineContextMenu, closePolylineContextMenu } from "../redux/slices/polylineContextMenuSlice";
|
||||
|
||||
// Funktion zum Deaktivieren der Polyline-Ereignisse
|
||||
export function disablePolylineEvents(polylines) {
|
||||
@@ -51,39 +52,60 @@ export function enablePolylineEvents(polylines, lineColors) {
|
||||
// Funktion zum Schließen des Kontextmenüs und Entfernen der Markierung
|
||||
function closePolylineSelectionAndContextMenu(map) {
|
||||
try {
|
||||
// Entferne alle markierten Polylinien
|
||||
// Falls eine Polyline aktiv ist, entfernen
|
||||
if (window.selectedPolyline) {
|
||||
window.selectedPolyline.setStyle({ weight: 3 }); // Originalstil wiederherstellen
|
||||
window.selectedPolyline.setStyle({ weight: 3 });
|
||||
window.selectedPolyline = null;
|
||||
}
|
||||
|
||||
// Überprüfe, ob map und map.contextmenu definiert sind
|
||||
if (map && map.contextmenu) {
|
||||
map.contextmenu.hide(); // Kontextmenü schließen
|
||||
// Überprüfen, ob das Kontextmenü existiert, bevor es geschlossen wird
|
||||
if (map && map.contextmenu && typeof map.contextmenu.hide === "function") {
|
||||
map.contextmenu.hide(); // Menü schließen
|
||||
} else {
|
||||
console.warn("Kontextmenü ist nicht verfügbar.");
|
||||
console.warn("Kontextmenü existiert nicht mehr oder wurde bereits entfernt.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Schließen des Kontextmenüs:", error);
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
// Countdown-Status zurücksetzen
|
||||
// Lokale Speicherwerte zurücksetzen
|
||||
localStorage.removeItem("contextMenuCountdown");
|
||||
localStorage.removeItem("contextMenuExpired");
|
||||
}
|
||||
|
||||
// Überprüft regelmäßig den Status in localStorage
|
||||
function monitorContextMenu(map) {
|
||||
setInterval(() => {
|
||||
function checkAndClose() {
|
||||
const isContextMenuExpired = localStorage.getItem("contextMenuExpired") === "true";
|
||||
if (isContextMenuExpired) {
|
||||
closePolylineSelectionAndContextMenu(map);
|
||||
localStorage.removeItem("contextMenuExpired"); // Flagge entfernen, um wiederverwendbar zu sein
|
||||
}
|
||||
}, 1000); // Alle 1 Sekunde überprüfen
|
||||
}
|
||||
|
||||
if (isContextMenuExpired) {
|
||||
if (map && map.contextmenu && typeof map.contextmenu.hide === "function") {
|
||||
closePolylineSelectionAndContextMenu(map);
|
||||
localStorage.removeItem("contextMenuExpired");
|
||||
} else {
|
||||
console.warn("Kontextmenü war nicht verfügbar und konnte nicht geschlossen werden.");
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(checkAndClose, 1000); // **Recursive Timeout statt Intervall**
|
||||
}
|
||||
|
||||
checkAndClose();
|
||||
}
|
||||
//------------------------------------------
|
||||
store.subscribe(() => {
|
||||
const state = store.getState(); // Redux-Toolkit empfohlene Methode
|
||||
if (state.polylineContextMenu.forceClose) {
|
||||
console.log("🚀 Redux-Event erkannt - Kontextmenü wird geschlossen.");
|
||||
store.dispatch(closePolylineContextMenu());
|
||||
|
||||
if (window.map && window.map.contextmenu) {
|
||||
window.map.contextmenu.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//--------------------------------------------
|
||||
export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible) => {
|
||||
if (!polylineVisible) {
|
||||
console.warn("Polylines deaktiviert - keine Zeichnung");
|
||||
@@ -292,7 +314,7 @@ export const setupPolylines = (map, linePositions, lineColors, tooltipContents,
|
||||
store.dispatch(openAddPoiOnPolylineModal(e.latlng));
|
||||
},
|
||||
},
|
||||
*/
|
||||
*/
|
||||
{
|
||||
text: "Stützpunkt hinzufügen",
|
||||
icon: "/img/icons/gisLines/add-support-point.svg",
|
||||
@@ -404,15 +426,32 @@ export const setupPolylines = (map, linePositions, lineColors, tooltipContents,
|
||||
localStorage.setItem("polylineLink", link);
|
||||
});
|
||||
*/
|
||||
// Starte den Timer zum Schließen des Kontextmenüs nach 15 Sekunden
|
||||
polyline.on("contextmenu", function (e) {
|
||||
const contextMenu = this._map.contextmenu; // Zugriff auf das Kontextmenü
|
||||
const closeMenu = () => contextMenu.hide(); // Funktion zum Schließen des Menüs
|
||||
|
||||
const countdown = parseInt(localStorage.getItem("contextMenuCountdown"), 30);
|
||||
if (countdown >= 28) {
|
||||
closeMenu();
|
||||
}
|
||||
// Event-Listener für Redux Store-Änderungen registrieren
|
||||
|
||||
// Starte den Timer zum Schließen des Kontextmenüs nach 15 Sekunden
|
||||
|
||||
polyline.on("contextmenu", (e) => {
|
||||
store.dispatch(closePolylineContextMenu());
|
||||
|
||||
setTimeout(() => {
|
||||
if (!map || !map.contextmenu) return;
|
||||
|
||||
store.dispatch(
|
||||
openPolylineContextMenu({
|
||||
position: { lat: e.latlng.lat, lng: e.latlng.lng },
|
||||
polylineId: polyline.options.idLD,
|
||||
})
|
||||
);
|
||||
|
||||
// Schließen nach 17 Sekunden
|
||||
setTimeout(() => {
|
||||
store.dispatch(closePolylineContextMenu());
|
||||
if (map.contextmenu) {
|
||||
map.contextmenu.hide();
|
||||
}
|
||||
}, 17000);
|
||||
}, 50);
|
||||
});
|
||||
|
||||
polylines.push(polyline);
|
||||
|
||||
Reference in New Issue
Block a user