From 0aa866bc6da060b5b933b8f57512fed692cfbcf5 Mon Sep 17 00:00:00 2001 From: Simon Seyock Date: Tue, 11 Jun 2024 15:41:36 +0200 Subject: [PATCH 1/2] fix: cleanup tooltips also when the containing component gets removed --- src/Hooks/useMeasure/useMeasure.ts | 154 ++++++++++++----------------- 1 file changed, 63 insertions(+), 91 deletions(-) diff --git a/src/Hooks/useMeasure/useMeasure.ts b/src/Hooks/useMeasure/useMeasure.ts index 6131d37..b9b7b9d 100644 --- a/src/Hooks/useMeasure/useMeasure.ts +++ b/src/Hooks/useMeasure/useMeasure.ts @@ -17,7 +17,7 @@ import OlStyleCircle from 'ol/style/Circle'; import OlStyleFill from 'ol/style/Fill'; import OlStyleStroke from 'ol/style/Stroke'; import OlStyleStyle from 'ol/style/Style'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { CSS_PREFIX } from '../../constants'; import useMap from '../useMap/useMap'; @@ -134,9 +134,10 @@ export const useMeasure = ({ }: UseMeasureProps) => { const [feature, setFeature] = useState>(); - const [measureTooltip, setMeasureTooltip] = useState(); - const [helpTooltip, setHelpTooltip] = useState(); - const [stepMeasureTooltips, setStepMeasureTooltips] = useState([]); + + const measureTooltip = useRef(); + const helpTooltip = useRef(); + const stepMeasureTooltips = useRef([]); const map = useMap(); @@ -214,93 +215,79 @@ export const useMeasure = ({ }, [measureType, measureLayer, fillColor, strokeColor, fillColor], active); const removeMeasureTooltip = useCallback(() => { - if (!map) { - return; - } - - if (measureTooltip) { - map.removeOverlay(measureTooltip); + if (map && measureTooltip.current) { + map.removeOverlay(measureTooltip.current); + measureTooltip.current = undefined } - - setMeasureTooltip(undefined); - }, [measureTooltip, map]); + }, [map]); const removeStepMeasureTooltips = useCallback(() => { - if (!map) { - return; - } - - if (stepMeasureTooltips.length > 0) { - stepMeasureTooltips.forEach(overlay => { + if (map && stepMeasureTooltips.current.length > 0) { + for (const overlay of stepMeasureTooltips.current) { map.removeOverlay(overlay); - }); + } - setStepMeasureTooltips([]); + stepMeasureTooltips.current = []; } - }, [stepMeasureTooltips, map]); + }, [map]); const removeHelpTooltip = useCallback(() => { - if (!map) { - return; + if (map && helpTooltip.current) { + map.removeOverlay(helpTooltip.current); + helpTooltip.current = undefined; } + }, [map]); - if (helpTooltip) { - map.removeOverlay(helpTooltip); - } - - setHelpTooltip(undefined); - }, [map, helpTooltip]); - - const cleanupTooltips = useCallback(() => { + const cleanup = useCallback(() => { removeMeasureTooltip(); - removeStepMeasureTooltips(); - removeHelpTooltip(); - }, [removeMeasureTooltip, removeStepMeasureTooltips, removeHelpTooltip]); + measureLayer?.getSource()?.clear(); + }, [measureLayer, removeMeasureTooltip, removeStepMeasureTooltips, removeHelpTooltip]); + + useEffect(() => { + if (active) { + return () => { + cleanup(); + }; + } + return undefined; + }, [active, cleanup]); const createHelpTooltip = useCallback(() => { - if (!map || helpTooltip) { + if (!map || helpTooltip.current) { return; } - const tooltip = document.createElement('div'); - tooltip.className = measureTooltipCssClasses?.tooltip ?? ''; - - const overlay = new OlOverlay({ - element: tooltip, + helpTooltip.current = new OlOverlay({ + element: document.createElement('div'), offset: [15, 0], - positioning: 'center-left' + positioning: 'center-left', + className: measureTooltipCssClasses?.tooltip ?? '' }); - setHelpTooltip(overlay); - - map.addOverlay(overlay); - }, [map, helpTooltip, measureTooltipCssClasses?.tooltip]); + map.addOverlay(helpTooltip.current); + }, [map, measureTooltipCssClasses?.tooltip]); const createMeasureTooltip = useCallback(() => { - if (!map || measureTooltip?.getElement()) { + if (!map || measureTooltip.current) { return; } - const element = document.createElement('div'); - if (measureTooltipCssClasses) { - element.className = `${measureTooltipCssClasses.tooltip} ${measureTooltipCssClasses.tooltipDynamic}`; - } - - const overlay = new OlOverlay({ - element: element, + measureTooltip.current = new OlOverlay({ + element: document.createElement('div'), offset: [0, -15], - positioning: 'bottom-center' + positioning: 'bottom-center', + className: measureTooltipCssClasses + ? `${measureTooltipCssClasses.tooltip} ${measureTooltipCssClasses.tooltipDynamic}` + : '' }); - setMeasureTooltip(overlay); - - map.addOverlay(overlay); + map.addOverlay(measureTooltip.current); }, [map, measureTooltip, measureTooltipCssClasses]); const updateMeasureTooltip = useCallback(() => { - if (!measureTooltip || !feature || !map) { + if (!measureTooltip.current || !feature || !map) { return; } @@ -344,31 +331,25 @@ export const useMeasure = ({ return; } - const el = measureTooltip.getElement(); + const el = measureTooltip.current.getElement(); if (output && el) { el.innerHTML = output; } - measureTooltip.setPosition(measureTooltipCoord); - }, [decimalPlacesInTooltips, feature, geodesic, map, measureTooltip, measureType, measureRadius]); + measureTooltip.current.setPosition(measureTooltipCoord); + }, [decimalPlacesInTooltips, feature, geodesic, map, measureType, measureRadius]); const onDrawStart = useCallback((evt: OlDrawEvent) => { - if (!measureLayer || !map) { + if (!map) { return; } - const source = measureLayer.getSource(); + if (!multipleDrawing) { + cleanup(); + } setFeature(evt.feature); - - const features = source?.getFeatures(); - - if (!multipleDrawing && features && features.length > 0) { - cleanupTooltips(); - - source?.clear(); - } - }, [cleanupTooltips, map, measureLayer, multipleDrawing]); + }, [cleanup, map, multipleDrawing]); const addMeasureStopTooltip = useCallback((coordinate: OlCoordinate) => { if (!feature || !map) { @@ -404,10 +385,9 @@ export const useMeasure = ({ tooltip.setPosition(coordinate); - setStepMeasureTooltips([...stepMeasureTooltips, tooltip]); + stepMeasureTooltips.current.push(tooltip); } - }, [stepMeasureTooltips, decimalPlacesInTooltips, feature, - geodesic, map, measureTooltipCssClasses, measureType]); + }, [decimalPlacesInTooltips, feature, geodesic, map, measureTooltipCssClasses, measureType]); const onDrawEnd = useCallback((evt: OlDrawEvent) => { if (multipleDrawing) { @@ -423,11 +403,11 @@ export const useMeasure = ({ ) { removeMeasureTooltip(); } else { - const el = measureTooltip?.getElement(); + const el = measureTooltip.current?.getElement(); if (el && measureTooltipCssClasses) { el.className = `${measureTooltipCssClasses.tooltip} ${measureTooltipCssClasses.tooltipStatic}`; } - measureTooltip?.setOffset([0, -7]); + measureTooltip.current?.setOffset([0, -7]); } updateMeasureTooltip(); @@ -440,18 +420,18 @@ export const useMeasure = ({ (multipleDrawing || showMeasureInfoOnClickedPoints) && (measureType === 'line' || measureType === 'polygon') ) { - measureTooltip?.setElement(undefined); + measureTooltip.current = undefined; createMeasureTooltip(); } - }, [addMeasureStopTooltip, createMeasureTooltip, measureTooltip, measureTooltipCssClasses, + }, [addMeasureStopTooltip, createMeasureTooltip, measureTooltipCssClasses, measureType, multipleDrawing, removeMeasureTooltip, showMeasureInfoOnClickedPoints, updateMeasureTooltip]); const updateHelpTooltip = useCallback((coordinate: OlCoordinate) => { - if (!helpTooltip) { + if (!helpTooltip.current) { return; } - const helpTooltipElement = helpTooltip?.getElement(); + const helpTooltipElement = helpTooltip.current?.getElement(); if (!helpTooltipElement) { return; @@ -468,7 +448,7 @@ export const useMeasure = ({ } helpTooltipElement.innerHTML = msg ?? ''; - helpTooltip.setPosition(coordinate); + helpTooltip.current.setPosition(coordinate); }, [clickToDrawText, continueAngleMsg, continueLineMsg, continuePolygonMsg, helpTooltip, measureType]); const onMapPointerMove = useCallback((evt: any) => { @@ -523,14 +503,6 @@ export const useMeasure = ({ } }, [createHelpTooltip, createMeasureTooltip, showHelpTooltip]); - useEffect(() => { - if (!active) { - measureLayer?.getSource()?.clear(); - - cleanupTooltips(); - } - }, [active, measureLayer, cleanupTooltips]); - useOlListener( feature, i => i.getGeometry()?.on('change', () => { From 6e5da12671318bce9ccf9e896c809e5e36c1bdda Mon Sep 17 00:00:00 2001 From: Simon Seyock <8100558+simonseyock@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:20:05 +0200 Subject: [PATCH 2/2] fix: missing semicolon Co-authored-by: Daniel Koch --- src/Hooks/useMeasure/useMeasure.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hooks/useMeasure/useMeasure.ts b/src/Hooks/useMeasure/useMeasure.ts index b9b7b9d..c0aa5d7 100644 --- a/src/Hooks/useMeasure/useMeasure.ts +++ b/src/Hooks/useMeasure/useMeasure.ts @@ -217,7 +217,7 @@ export const useMeasure = ({ const removeMeasureTooltip = useCallback(() => { if (map && measureTooltip.current) { map.removeOverlay(measureTooltip.current); - measureTooltip.current = undefined + measureTooltip.current = undefined; } }, [map]);