diff --git a/packages/react-leaflet/src/Marker.tsx b/packages/react-leaflet/src/Marker.tsx index f50cc3e3..7baadc85 100755 --- a/packages/react-leaflet/src/Marker.tsx +++ b/packages/react-leaflet/src/Marker.tsx @@ -5,7 +5,10 @@ import { extendContext, } from '@react-leaflet/core' import { + LatLng, type LatLngExpression, + type LatLngLiteral, + type LatLngTuple, Marker as LeafletMarker, type MarkerOptions, } from 'leaflet' @@ -16,6 +19,47 @@ export interface MarkerProps extends MarkerOptions, EventedProps { position: LatLngExpression } +function arraysEqual(arr1: LatLngTuple, arr2: LatLngTuple) { + return arr1.every((value, index) => value === arr2[index]) +} + +function objectsEqual(obj1: LatLngLiteral, obj2: LatLngLiteral) { + return Object.keys(obj1).every( + (key) => + obj1[key as keyof LatLngLiteral] === obj2[key as keyof LatLngLiteral], + ) +} + +function handlePositionUpdate( + marker: LeafletMarker, + props: MarkerProps, + prevProps: MarkerProps, +) { + if ( + props.position instanceof LatLng && + !props.position.equals(prevProps.position) + ) { + return marker.setLatLng(props.position) + } + + if ( + Array.isArray(props.position) && + !arraysEqual(props.position, prevProps.position as LatLngTuple) + ) { + return marker.setLatLng(props.position) + } + + // if position is not a LatLng or LatLngTuple, it must be the LatLngLiteral object + if ( + !objectsEqual( + props.position as LatLngLiteral, + prevProps.position as LatLngLiteral, + ) + ) { + return marker.setLatLng(props.position) + } +} + export const Marker = createLayerComponent( function createMarker({ position, ...options }, ctx) { const marker = new LeafletMarker(position, options) @@ -25,9 +69,8 @@ export const Marker = createLayerComponent( ) }, function updateMarker(marker, props, prevProps) { - if (props.position !== prevProps.position) { - marker.setLatLng(props.position) - } + handlePositionUpdate(marker, props, prevProps) + if (props.icon != null && props.icon !== prevProps.icon) { marker.setIcon(props.icon) }