**The error is a result of a combination of react and leaflet and leaflet-markercluster, but the original source of the error is leaflet
UPDATE: it's reproducible with just leaflet
Expect: setLatLng should work for CircleMarkers like it does for Markers
Reality: setLatLng leads to undefined errors
I originally experienced the error using the marker cluster plugin, but it's reproducible without it.
Related issue: https://github.com/YUzhva/react-leaflet-markercluster/issues/31
Error stack trace in leaflet-markercluster:
leaflet-src.js:1658 Uncaught TypeError: Cannot read property 'lat' of undefined
at Object.project (leaflet-src.js:1658)
at Object.latLngToPoint (leaflet-src.js:1497)
at NewClass.project (leaflet-src.js:3931)
at NewClass._removeFromGridUnclustered (leaflet.markercluster-src.js:690)
at NewClass._removeLayer (leaflet.markercluster-src.js:738)
at NewClass.removeLayer (leaflet.markercluster-src.js:181)
at NewClass._moveChild (leaflet.markercluster-src.js:713)
at NewClass._childMarkerMoved (leaflet.markercluster-src.js:703)
at NewClass.fire (leaflet-src.js:592)
at NewClass.setLatLng (leaflet-src.js:7843)
The problem is that e.oldLatLng is undefined here in leaflet-markercluster:
_childMarkerMoved: function (e) {
if (!this._ignoreMove && !e.target.__dragStart) {
var isPopupOpen = e.target._popup && e.target._popup.isOpen();
this._moveChild(e.target, e.oldLatLng, e.latlng);
if (isPopupOpen) {
e.target.openPopup();
}
}
},
How is this a leaflet issue? When you fire a move end it seems to expect both a 'from' (oldLatLng) and a 'to' (latlng).
This is what setLatLng looks like for vanilla Markers:
setLatLng: function (latlng) {
var oldLatLng = this._latlng;
this._latlng = toLatLng(latlng);
this.update();
return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
}
and this is what it looks like for CircleMarkers:
setLatLng: function (latlng) {
this._latlng = toLatLng(latlng);
this.redraw();
return this.fire('move', {latlng: this._latlng});
},
It doesn't set oldLatLng, so it's undefined when the move event fires.
Changing CircleMarker's setLatLng to this fixes the issue:
setLatLng: function (latlng) {
var oldLatLng = this._latlng;
this._latlng = toLatLng(latlng);
this._update();
return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
},
https://codepen.io/mmacquarrie/pen/VBMRva~~
UPDATE: https://codepen.io/mmacquarrie/pen/ajqKZW
Hi,
Thank you for your report.
It seems to me that you essentially point out an inconsistency of the "move" event of Circle Markers compared to Markers.
The docs for the latter clearly mention the 2 properties indeed:
Old and new coordinates are included in event arguments as
oldLatLng,latlng.
But there is no doc at all for the former.
Because both Circle Marker and Marker address a very similar usage, we could expect a similar API. Especially in this case where both provide a setLatLng method that does the same thing, except for the data associated to this "move" event.
If I understand correctly, that is what happened when you used Leaflet.markercluster plugin and filled it with Circle Markers.
While in your case you use React, you should have been able to build an example without it at all.
BTW, while the related issue you mention describes a similar error and also code with setLatLng (that is never executed), it seems to me that it describes a totally different situation.
Looking at the history behind oldLatLng in Marker "move" event, it was specifically introduced for Leaflet.markercluster plugin by PR https://github.com/Leaflet/Leaflet/pull/2412.
Since this plugin happily accepts Circle Markers, it is definitely an inconsistency not doing the same for Circle Marker "move" event.
Yes, my problem is the inconsistency between setLatLng for Markers and CircleMarkers, especially since the documentation says you can call setLatLng on the latter.
The related issue is the context in which I originally found the error. I wanted to make the codepen simpler, though, and just call the function that was causing the problem, so you're right that it seems like a totally different situation.
Here's a much simpler codepen that reproduces the issue with no third party code whatsoever:
https://codepen.io/mmacquarrie/pen/ajqKZW
And update on this? I'm also getting the error specifically with CircleMarkers.
If I switch to a regular marker, it works fine.
This is still an ongoing problem. I faced the same issue when using CircleMarker with react-leaflet-markercluster. I fixed this creating a custom wrapper and overriding setLatLng of L.CircleMarker. Here is the code if anyone wants to check it.
import { CircleMarker as LeafletCircleMarker } from 'leaflet'
import { withLeaflet, Path } from 'react-leaflet';
LeafletCircleMarker.include({
setLatLng: function (latlng) {
const oldLatLng = this._latlng;
this._update();
return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
},
})
class CircleMarker extends Path {
createLeafletElement({ position, leaflet, ...options }) {
return new LeafletCircleMarker(position, options);
}
updateLeafletElement(fromProps, { position, radius }) {
if (position !== fromProps.position) {
this.leafletElement.setLatLng(position);
}
if (radius !== fromProps.radius) {
this.leafletElement.setRadius(radius);
}
}
}
export default withLeaflet(CircleMarker);
@Nadhum thanks a lot for your solution. I was having the same: MarkerClusterGroup with CircleMarkers inside was throwing this error: https://github.com/YUzhva/react-leaflet-markercluster/issues/31.
This fixes it straight away if, when creating the CircleMarker, I pass not only the center, but also position prop
<CircleMarker
center={latlng}
position={latlng}
</CircleMarker>
Fixed by PR #6719
Fixed by PR #6719
Confirmed, upgrade to leaflet 1.6 fixes this issue for me.
Most helpful comment
This is still an ongoing problem. I faced the same issue when using CircleMarker with react-leaflet-markercluster. I fixed this creating a custom wrapper and overriding setLatLng of L.CircleMarker. Here is the code if anyone wants to check it.