mirror of
https://github.com/usememos/memos.git
synced 2025-12-11 14:46:03 +08:00
fix(web): resolve Leaflet DOM cleanup error causing app crashes
- Add MapCleanup component to properly remove Leaflet map instances on unmount - Fix LocationMarker initialization with useRef to prevent re-initialization - Remove problematic key prop in LocationDialog that caused unnecessary remounts - Fix goimports formatting in tag parser Fixes #5260
This commit is contained in:
parent
3989100a27
commit
cabd0d61c6
2 changed files with 32 additions and 6 deletions
|
|
@ -1,8 +1,8 @@
|
|||
import { DivIcon, LatLng } from "leaflet";
|
||||
import { MapPinIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import ReactDOMServer from "react-dom/server";
|
||||
import { MapContainer, Marker, TileLayer, useMapEvents } from "react-leaflet";
|
||||
import { MapContainer, Marker, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
||||
|
||||
const markerIcon = new DivIcon({
|
||||
className: "relative border-none",
|
||||
|
|
@ -17,6 +17,7 @@ interface MarkerProps {
|
|||
|
||||
const LocationMarker = (props: MarkerProps) => {
|
||||
const [position, setPosition] = useState(props.position);
|
||||
const initializedRef = useRef(false);
|
||||
|
||||
const map = useMapEvents({
|
||||
click(e) {
|
||||
|
|
@ -33,9 +34,12 @@ const LocationMarker = (props: MarkerProps) => {
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
map.attributionControl.setPrefix("");
|
||||
map.locate();
|
||||
}, []);
|
||||
if (!initializedRef.current) {
|
||||
map.attributionControl.setPrefix("");
|
||||
map.locate();
|
||||
initializedRef.current = true;
|
||||
}
|
||||
}, [map]);
|
||||
|
||||
// Keep marker and map in sync with external position updates
|
||||
useEffect(() => {
|
||||
|
|
@ -50,6 +54,27 @@ const LocationMarker = (props: MarkerProps) => {
|
|||
return position === undefined ? null : <Marker position={position} icon={markerIcon}></Marker>;
|
||||
};
|
||||
|
||||
const MapCleanup = () => {
|
||||
const map = useMap();
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
// Cleanup map instance when component unmounts
|
||||
setTimeout(() => {
|
||||
if (map) {
|
||||
try {
|
||||
map.remove();
|
||||
} catch {
|
||||
// Ignore errors during cleanup
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
}, [map]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
interface MapProps {
|
||||
readonly?: boolean;
|
||||
latlng?: LatLng;
|
||||
|
|
@ -64,6 +89,7 @@ const LeafletMap = (props: MapProps) => {
|
|||
<MapContainer className="w-full h-72" center={position} zoom={13} scrollWheelZoom={false}>
|
||||
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
|
||||
<LocationMarker position={position} readonly={props.readonly} onChange={props.onChange ? props.onChange : () => {}} />
|
||||
<MapCleanup />
|
||||
</MapContainer>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export const LocationDialog = ({
|
|||
</VisuallyHidden>
|
||||
<div className="flex flex-col">
|
||||
<div className="w-full h-64 overflow-hidden rounded-t-md bg-muted/30">
|
||||
<LeafletMap key={JSON.stringify(locationInitialized)} latlng={position} onChange={onPositionChange} />
|
||||
<LeafletMap latlng={position} onChange={onPositionChange} />
|
||||
</div>
|
||||
<div className="w-full flex flex-col p-3 gap-3">
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue