1
votes

I'm encountering an issue with React native maps. I try to put markers on my maps, and highlight the pressed marker. I wouldn't think this would be that tricky :)

Here's how I render my markers:

function renderMarkers() {
    const shopsFiltered = shops.filter((shop) => {      
      return shop.hasOwnProperty('latitude') && shop.hasOwnProperty('longitude') && shop.latitude && shop.longitude
    });
    return shopsFiltered.map((shop) => {
      
      const isInWallet = cards.data.filter(card => {
        return card.hasOwnProperty('company') && shop.hasOwnProperty('company') && card.company.objectId === shop.company.objectId;
      }).length;
      const isCurrentMarker = shop.company.objectId === currentMarkerCardId;
      const latLng = { latitude: shop.latitude, longitude: shop.longitude };
      return <Marker  
        key={shop.objectId}
        coordinate={latLng}
        onPress={() => onMarkerPress(shop.company.objectId)}
      >
        {isCurrentMarker && // I had to do this, since the dimensions weren't updated using style prop...
          <Image
            source={isInWallet ? require('../assets/images/explorer/pin-on.png'):require('../assets/images/explorer/pin-off.png')}
            style={styles.mapMarkerCurrent }
            resizeMode="cover"
            resizeMethod="resize"
          />
        }
        {!isCurrentMarker &&
          <Image
            source={isInWallet ? require('../assets/images/explorer/pin-on.png'):require('../assets/images/explorer/pin-off.png')}
            style={styles.mapMarker}
            resizeMode="cover"
            resizeMethod="resize"
          />
        }

      </Marker>
    });
  }

When I press a marker:

function onMarkerPress(id) {
  setBottomBoxOpacity(1);
  setCurrentMarkerCardId(id);
}

setCurrentMarkerCardId is a useState hook, and therefore rerender the view. That's a problem in my case, because the whole map rerender (= it recenter the map on the user's position) and causes the map to be laggy.

However, I see the issue, but I don't know how to update the pressed marker value without rerendering the whole map.

Any ideas?

EDIT:

Still using my component state, I'm able to hack this map:

function onMarkerPress(id, coordinate) {
    setBottomBoxOpacity(1);
    setCurrentMarkerCardId(id);
    setMapState({
      ...mapState,
      region: {
        ...mapState.region,
        latitude: coordinate.latitude,
        longitude: coordinate.longitude
      }
    })
  }

And I had to set moveOnMarkerPress={false} on the MapView component.

So, basically, on each Marker press, I'm updating state with Marker's latlng, and rerendering the map with the pressed Marker's latlng used as the center of the map.

It feels hacky, and it's not perfect. I can't use animatetoregion method : as I updated the state, the MapView rerenders and cut the anim.

1
In my case what I did for on click on Marker , I use Callout . You can use useEffect for render. and pass the selected lat long with delta. Can you please explain the scenario? I think you are coming to MapScreen from somewhere and u habe the selected data lat long Id and , you have to highlight this. Correct?Rajshekhar Yadav
The scenario is the following: when I press a marker, I want to highlight it (with a different image and styles). I've done it (see my edit) in a hacky way, I'm looking for a clean solution.enguerranws
What i hv done in my case when i click on marker. I show a tooltip on click of maeker. I can share u details.Rajshekhar Yadav
onPressMarker(e, index) { setState({selectedMarkerIndex: index}); } YourList.map((m, i) => <MapView.Marker coordinate={m.latLong} title={m.title} description={m.description} key={marker-${i}} onPress={(e) => this.onPressMarker(e, i)} image={this.state.selectedMarkerIndex === i ? selectedMarker : marker} // this is the crux of the blog />Rajshekhar Yadav
You can use..callOut is method inside marker to customise the markerRajshekhar Yadav

1 Answers

0
votes

Ok, I'm feeling really silly.

The answer was just there the whole time. I made a mistake using region prop, when I should use initialRegion on the MapView component (that I didn't include in the question :/), which, according to the doc is only used when the component has mounted:

Changing this prop after the component has mounted will not result in a region change.