Open PeteMac3D opened 1 year ago
Thanks for opening your first issue here! This space is protected by our Code of Conduct - and we're here to help. Please follow the issue template to help us help you 👍🎉😄 If you have screenshots or a gif to share demonstrating the issue, that's really helpful! 📸 You can make a gif too! Do join our Gitter channel for some brainstorming discussions.
visual of the problem for context
Fixed the problem for anyone who find a problem implementing DistortableImage into React /React leaflet - think it relates to issue #1381 in a way with
map.remove()
crashing the app at the start of my error tree MapContainer had a clean up function in a useEffect
useEffect(()=>{
return ()=>{
context?.map.remove()};}, [context ]);
context being from @react-leaflet/core
I used #1381 solution getting reference to the map via context and it works as expected
context?.map.eachLayer(layer => {
// @ts-ignore
if (layer.editing) {
// @ts-ignore
const layers = layer.editing.currentHandle?._layers ?? {};
// @ts-ignore
Object.values(layers).forEach(layer => layer.remove());
// @ts-ignore
layer.editing.currentHandle = null;
}
layer.remove();
});
context?.map.remove();
I believe it's a similar issue to one we experienced when unmounting the whole map: #1381
The whole remove operation errors because removing each individual layer fails if it's a DistortableImage layer with certain handles like you described. I'm not sure what causes it but we did find a hacky workaround.
I suggest you keep track of L.DistortableImageLayer in your hook and unmount it like this:
/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ ts-ignore
if (layer.editing) {
// @ts-ignore
const layers = layer.editing.currentHandle?._layers ?? {};
// @ts-ignore
Object.values(layers).forEach(layer => layer.remove());
// @ts-ignore
layer.editing.currentHandle = null;
}
layer.remove();
/* eslint-enable @typescript-eslint/ban-ts-comment */
I'm not entirely sure this will work for your in your case but we also had problems when removing individual layers like I assume you are trying to do. When attempting to remove the entire map after this, our app crashed just like yours does.
The error we were getting was slightly different but also occurred in _unbindListeners
of editHandle.js
, so maybe give it a shot!
Edit: beat me to it 😄
@jpoep a simultaneous response :D Thanks for you post -massive help
Any updates on this issue?
I believe it's a similar issue to one we experienced when unmounting the whole map: #1381
The whole remove operation errors because removing each individual layer fails if it's a DistortableImage layer with certain handles like you described. I'm not sure what causes it but we did find a hacky workaround.
I suggest you keep track of L.DistortableImageLayer in your hook and unmount it like this:
/* eslint-disable @typescript-eslint/ban-ts-comment */ // @ ts-ignore if (layer.editing) { // @ts-ignore const layers = layer.editing.currentHandle?._layers ?? {}; // @ts-ignore Object.values(layers).forEach(layer => layer.remove()); // @ts-ignore layer.editing.currentHandle = null; } layer.remove(); /* eslint-enable @typescript-eslint/ban-ts-comment */
I'm not entirely sure this will work for your in your case but we also had problems when removing individual layers like I assume you are trying to do. When attempting to remove the entire map after this, our app crashed just like yours does.
The error we were getting was slightly different but also occurred in
_unbindListeners
ofeditHandle.js
, so maybe give it a shot!Edit: beat me to it 😄
thank you for this solution. finally, i solved this issue but i have confused when call this logic in hooks, for like me, i remain my code ~ i`m using unload event hooks
import {useMapEvent} from 'react-leaflet';
import L from 'leaflet';
import 'leaflet-toolbar';
import 'leaflet-distortableimage';
import 'leaflet-toolbar/dist/leaflet.toolbar.css';
import 'leaflet-distortableimage/dist/leaflet.distortableimage.css';
import {forwardRef, useEffect, useImperativeHandle, useState} from 'react';
import {Path} from '../types';
interface IDistortableImageOverlayProps {
editable: boolean;
mapCenter: [number, number];
imageUrl: string;
corners?: Path[];
}
export default forwardRef(
(
{editable, mapCenter, imageUrl, corners}: IDistortableImageOverlayProps,
ref,
) => {
const map = useMapEvent('unload', () => {
map.eachLayer((layer: any) => {
// @ts-ignore
if (layer.editing) {
// @ts-ignore
const layers = layer.editing.currentHandle?._layers ?? {};
// @ts-ignore
Object.values(layers).forEach((layer) => layer.remove());
// @ts-ignore
layer.editing.currentHandle = null;
}
layer.remove();
});
});
const [layer, setLayer] = useState<any>(null);
const getCorners = () => {
return layer ? layer.getCorners() : [];
};
useImperativeHandle(ref, () => ({
getCorners,
}));
useEffect(() => {
if (!layer) {
map.whenReady(() => {
//@ts-ignore
const newLayer = L.distortableImageOverlay(imageUrl, {
corners,
editable,
zIndex: 401,
actions: [
// @ts-ignore
L.DragAction,
// @ts-ignore
L.ScaleAction,
// @ts-ignore
L.DistortAction,
// @ts-ignore
L.RotateAction,
// @ts-ignore
L.FreeRotateAction,
// @ts-ignore
L.BorderAction,
],
});
setLayer(newLayer);
});
}
}, []);
useEffect(() => {
if (map && layer) {
layer.addTo(map);
layer.setOpacity(0.7);
}
}, [layer]);
return null;
},
);
Scope: React v.18.2.0, vite v.4.4.5, React-Leaflet: v4.2.1, Leaflet.DistortableImage: v0.21.9
Description: Not sure if this is a bug, my usage, or simply DistortableImage isn't set up for use in React? Destroying a component results in a crash of the app, specifically if I included the action L.RotateAction or L.LockAction (pass in as an array or used as default) When I have these eliminated everything works as expected.
Think the problem lays with the unbinding of the event handlers and the loss of context relating to 'this' , initialized by React during diffing stage ?
See console error(s)
offending line of code in editHandle.js
useEffect in compoment
Parent component
As a side note I tried to remove the action in useEffect (using the useeffect clean up function) but cannot locate the method 'removeTool' I dont see it on any of the instances prototypes ?