react-native-maps: Custom Markers does not update after props change on Android

Hi everyone,

I’m having an issue on Android where the custom marker does not update after its props have change.

When i press the marker, its marked like selected and vice versa. Then its backgroundColor changes to identify that it has beed selected or not. This is working fine on iOS - Mapkit but on Android - Google Map does not update the change.

On Android - Google Map. Does not update the change.

android

On iOS - Mapkit works perfectly. This is the expected behavior.

ios

Here is my code.

State and method

state = {
    selected: [],
  }

toggleSelect(id) {
    this.state.selected.indexOf(id) > -1
      ? this.setState({ selected: this.state.selected.filter(x => x !== id) })
      : this.setState({ selected: this.state.selected.concat(id) })
  }

MapView Component

<MapView
                style={styles.contentTabView}
                initialRegion={{
                  latitude: -33.447984,
                  longitude: -70.659059,
                  latitudeDelta: 0.0922,
                  longitudeDelta: 0.0421,
                }}
              >
                {data.map(x =>
                  <MapView.Marker
                    key={x._id}
                    coordinate={{
                      longitude: x.location.coordinates[0],
                      latitude: x.location.coordinates[1],
                    }}
                    title={x.name}
                    centerOffset={{ x: 0, y: -20 }}
                    onPress={() => !(x.origin || x.destination) && this.toggleSelect(x._id)}
                  >

                    <Pin
                      pinStyle='pinIcon'
                      sourceIcon={x.clasification.icon}
                      id={x._id}
                      selected={selected}
                      origin={x.origin}
                      destination={x.destination}
                      color={x.timePeriod.color}
                    />
                  </MapView.Marker>
                )}
              </MapView>

Custom Marker Component

<View style={styles[pinStyle].container}>
        <View style={[
          styles[pinStyle].wrapper,
          wrapperColor,
          isSelected(id, selected) && styles[pinStyle].pointSelected,
          (origin || destination) && styles[pinStyle].pointSelected,
        ]}>
          <View style={styles[pinStyle].inner}>
            {type === 'icon'
              ? <IconAwesome
                style={styles[pinStyle].icon}
                name={sourceIcon ? sourceIcon : 'plane'}
              />
              : <Image
                style={styles[pinStyle].image}
                source={{ uri: sourceImg }}
              />}
          </View>
        </View>
      </View>

Helper function

export const isSelected = (_id, selected) => selected.indexOf(_id) > -1 ? true : false

Tell me if you need more details. Thanks.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 12
  • Comments: 19 (1 by maintainers)

Commits related to this issue

Most upvoted comments

Android seems to be relying only on the key to change in order to update the custom marker. When you re-render try changing your key. This works for me:


<MapView.Marker
  key={ `${marker.id}${Date.now()}` }
  coordinate={ marker }
>
  <CustomMarker marker={marker}>
</MapView.Marker>

I used the Date.now() as suggested by @chrismcleod in key={ ${marker.id}${Date.now()} }, but I found it caused a huge performance loss, instead I used the value the marker update depends on to change the key, and that worked well. In my case I wanted to update marker colors so I used: key={ ${key}${marker[key].color} }

Date.now() cause a huge performance loss. It re-creates the marker instead of re-render every time.

      tracksViewChanges={true}

use this in the marker

For android it does not work It seems

      tracksViewChanges={true}

use this in the marker

+1, same here!!

There’s a solution?

Nice bug 😦 let’s hack everything a little more to find a workaround.

When i click on the market it re-render how i expected but then it hides the infowindow.

I ran into the same issue. Solved this way:

<MapView.Marker
    coordinate={ position }
    key={`${x._id}${isSelected(x._id) ? '-selected' : ''}`} // <-- updates only selected (and deselected) marker
    identifier={x._id} // <-- we need this to invoke showCallout
    ref={(ref) => this._markers[x._id] = ref} // <-- store ref
    onPress={this._onPressMarker}
>
onPressMarker(e) {
  setTimeout(() => // sadly, we need timeout to make this command run in next cycle, after map updates.
    this._markers[e.nativeEvent.id].showCallout()
    , 0);
}

image