react-native-maps pin switches to another pin in close proximity on apple maps

136 Views Asked by At

I am running into an odd problem with apple maps in react-native-maps. Whenever a pin is clicked, it switches to another pin when they are in close proximity to each other, please see the gifs below for a clearer idea of what is wrong. Additionally, when dragging a pin, it results in many onpress calls. Is there any way to suppress it? For each marker, No "onPress", "onDrag", or their variations help in this behaviour. Even removing onPress, or onSelect methods entirely do nothing to help this behaviour. Any help would be appreciated.

It is easier to show with a gif:

Gif of problem

There is also unexpected behaviour when dragging points on the map:

dragging on pins

Here is my Mapview Component:

<MapView
        //provider={PROVIDER_GOOGLE} use apple maps on ios
        //
        showsBuildings={false}
        showsTraffic={false}
        showsIndoors={false}
        showsCompass={false}
        showsScale={false}
        //
        //
        initialRegion={{
          latitude: -25.2743988,
          longitude: 133.7751312,
          latitudeDelta: 40,
          longitudeDelta: 40,
        }}
        style={styles.map}
        showsUserLocation
        showsMyLocationButton={false}
        ref={mapRef}
      >
        {markedPlaces.map((place) => (
          <MapMarker
          key={place.placeId}
          place={place}
          placeInfo={placeInfo}
          onPress={() => handleFocusPlace(place)}/>
          )
        )
        }
</MapView>

And my marker component:

import React from 'react';
import { Marker } from 'react-native-maps';
import { Place } from '../../models';
import { createDescription, createPinColor } from './utils';

type MapMarkerProps = {
  place: Place;
  placeInfo: Place | null;
  onPress: (place: Place) => void;
};

const MapMarker: React.FC<MapMarkerProps> = React.memo(({ place, placeInfo, onPress }) => {
  //console.log('Place Data:', place)
  //console.log("placeinfo data:", placeInfo)
  //console.log("place rating for this marker:", place.rating)
  const description = createDescription(place);
  const pinColor = createPinColor(place.rating);

  return (
    <Marker
      key={place.placeId}
      coordinate={place.location}
      title={place.name}
      description={description}
      onPress={() => onPress(place)}
      onCalloutPress={() => onPress(place)}
      pinColor={pinColor}
      tracksViewChanges={false}
      //may need to disable on android
      stopPropagation={true}
      onSelect={() => onPress(place)}
      //onDeselect={() => onPress(place)}



      
    />
  );
});

export default MapMarker;
1

There are 1 best solutions below

0
Fotios Tsakiris On

Use clustering, to group the markers together when they are in close proximity to each other.


<MapView
  // ...
  cluster={true}
  radius={50}
  maxZoomLevel={15}
>
  {markedPlaces.map((place) => (
    <MapMarker
      key={place.placeId}
      place={place}
      placeInfo={placeInfo}
      onPress={() => handleFocusPlace(place)}
    />
  ))}
</MapView>

To prevent onPress firing multiple times, you can debounce the function call using lodash.debounce.

import React from 'react';
import { Marker } from 'react-native-maps';
import { Place } from '../../models';
import { createDescription, createPinColor } from './utils';
import debounce from 'lodash.debounce';

type MapMarkerProps = {
  place: Place;
  placeInfo: Place | null;
  onPress: (place: Place) => void;
};

const MapMarker: React.FC<MapMarkerProps> = React.memo(({ place, placeInfo, onPress }) => {
  const description = createDescription(place);
  const pinColor = createPinColor(place.rating);

  // Debounce the onPress event to prevent multiple calls when dragging the marker
  const handlePress = React.useMemo(() => debounce(onPress, 100, { leading: true, trailing: false }), [onPress]);

  return (
    <Marker
      // ...
      onPress={() => handlePress(place)}
      onCalloutPress={() => handlePress(place)}
      onSelect={() => handlePress(place)}
    />
  );
});

export default MapMarker;