Skip to content

Commit 30577c1

Browse files
iobuhovclaude
andcommitted
refactor(maps-web): use ref callback with disposeMap instead of useEffect
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 0d340b9 commit 30577c1

2 files changed

Lines changed: 23 additions & 24 deletions

File tree

packages/pluggableWidgets/maps-web/src/components/LeafletMap.tsx

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import classNames from "classnames";
2-
import { ReactElement, useEffect, useRef } from "react";
2+
import { ReactElement, useCallback } from "react";
33
import { getDimensions } from "@mendix/widget-plugin-platform/utils/get-dimensions";
44
import { MapProviderEnum } from "../../typings/MapsProps";
55
import { SharedProps } from "../../typings/shared";
@@ -12,27 +12,24 @@ export interface LeafletProps extends SharedProps {
1212

1313
export function LeafletMap(props: LeafletProps): ReactElement {
1414
const vm = useLeafletMapVM();
15-
const mapNodeRef = useRef<HTMLDivElement | null>(null);
1615

17-
useEffect(() => {
18-
const node = mapNodeRef.current;
19-
if (!node) {
20-
return;
21-
}
22-
23-
const cleanup = vm.setupMap(node);
24-
25-
return () => {
26-
cleanup();
27-
};
28-
}, [vm]);
16+
const refCallback = useCallback(
17+
(node: HTMLDivElement | null) => {
18+
if (node) {
19+
vm.setupMap(node);
20+
} else {
21+
vm.disposeMap();
22+
}
23+
},
24+
[vm]
25+
);
2926

3027
return (
3128
<div className={classNames("widget-maps", props.className)} style={{ ...props.style, ...getDimensions(props) }}>
3229
<div className="widget-leaflet-maps-wrapper">
3330
<div
3431
className="widget-leaflet-maps"
35-
ref={mapNodeRef}
32+
ref={refCallback}
3633
style={{ top: 0, bottom: 0, left: 0, right: 0, position: "absolute", zIndex: 1 }}
3734
/>
3835
</div>

packages/pluggableWidgets/maps-web/src/model/viewmodels/LeafletMap.viewModel.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class LeafletMapViewModel {
1313
private map: LeafletMapInstance | undefined = undefined;
1414
private tileLayer: TileLayer | undefined = undefined;
1515
private leafletMarkers: LeafletMarker[] = [];
16+
private disposeReaction: (() => void) | undefined = undefined;
1617

1718
constructor(
1819
private readonly gate: DerivedPropsGate<MapsContainerProps>,
@@ -25,7 +26,7 @@ export class LeafletMapViewModel {
2526
return this.gate.props.mapProvider;
2627
}
2728

28-
setupMap(node: HTMLDivElement): () => void {
29+
setupMap(node: HTMLDivElement): void {
2930
const {
3031
attributionControl,
3132
optionDrag: dragging,
@@ -53,22 +54,23 @@ export class LeafletMapViewModel {
5354
this.tileLayer = new TileLayer(url, options);
5455
this.tileLayer.addTo(map);
5556

56-
const dispose = reaction(
57+
this.disposeReaction = reaction(
5758
() => ({
5859
locations: this.locationResolver.locations,
5960
currentLocation: this.currentLocationService.location
6061
}),
6162
({ locations, currentLocation }) => this.syncMarkers(locations, currentLocation, autoZoom),
6263
{ fireImmediately: true }
6364
);
65+
}
6466

65-
return () => {
66-
dispose();
67-
this.leafletMarkers = [];
68-
this.tileLayer = undefined;
69-
this.map = undefined;
70-
map.remove();
71-
};
67+
disposeMap(): void {
68+
this.disposeReaction?.();
69+
this.disposeReaction = undefined;
70+
this.leafletMarkers = [];
71+
this.tileLayer = undefined;
72+
this.map?.remove();
73+
this.map = undefined;
7274
}
7375

7476
private syncMarkers(locations: Marker[], currentLocation: Marker | undefined, autoZoom: boolean): void {

0 commit comments

Comments
 (0)