Suat Alkan
Suat Alkan

Reputation: 103

prevent re-render of every marker when a state has changed

I'm currently working on a hobby project that involves implementing a map system with custom markers. The challenge I'm encountering is that every marker on the map undergoes a re-render, even when the changed state isn't utilized by the map or markers themselves.

As a test, I've written the following code:

const [test, setTest] = useState(false);

const handleMapPress = () => {
  setTest(!test);
}

The handleMapPress function is triggered when the onPress event occurs on the MapView. Despite the fact that test is not used anywhere else in the component, all of the markers undergo a re-render, resulting in flickering on my display.

I have tried React.memo but the markers still re-render.

I'm seeking advice on how to address this issue.

Edit: added current code for MapMarker

      const MapMarker = ({ coordinate, isActive, onPress }) => {
        return (
          <Marker coordinate={coordinate}>
            <TouchableOpacity onPress={onPress}>
              <Image
                source={
                  isActive
                    ? require('assets/icons8-map-marker2-64.png')
                    : require('assets/icons8-map-marker-64.png')
                }
                style={{ width: 30, height: 30 }}
              />
            </TouchableOpacity>
          </Marker>
        );
      };

      return (
        <View
          style={[
            mapStyles.container,
            {
              flexDirection: 'column'
            },
          ]}>
          {(
          <MapView 
            initialRegion={initialRegion} 
            style={[styles.container]} 
            onRegionChangeComplete={this.onRegionChange} 
            onPress={handleMapPress}>
              {data.map((item, index) => (
                <MapMarker
                  isActive={index === activeMarker}
                  onPress={() => handleMarkerPress(index, item)}
                  value={item}
                  key={index}
                  coordinate={{
                    latitude: item.latitude,
                    longitude: item.longitude,
                  }}
                />
              ))}
          </MapView>
          )}
        </View>
      );

Upvotes: 0

Views: 853

Answers (2)

perhaps what I'm about to say next could be of help to you, as it helped me in an Uber-like app that is currently in production:

It's not recommended to use within . Instead, utilize the "icon" property of the component and ensure two things:

  1. Ensure that the "key" property is unique and doesn't change with state changes, whether it's an ID or something fixed.

  2. Ensure that the image you use in "icon" is of the exact size you want it to be displayed, for example: 30x30, as you cannot define dimensions in the "icon" property.

With this, the marker should stop rendering or flickering, as was the case with mine.

import carIcon from './assets/images/carIcon.png';

<Marker
 coordinate={coordinate}
 icon={carIcon} //Your custom image her
/>
         

Upvotes: 0

talhamaqsood890
talhamaqsood890

Reputation: 369

The issue you're facing with markers re-rendering when there's a state change that doesn't affect them is likely due to the fact that your MapMarker component is not being memorized correctly. React.memo is a useful tool to prevent unnecessary re-renders.

  const MapMarker = React.memo(
    ({ coordinate, isActive, onPress }) => {
      return (
        <Marker coordinate={coordinate}>
          <TouchableOpacity onPress={onPress}>
            <Image
              source={
                isActive
                  ? require('assets/icons8-map-marker2-64.png')
                  : require('assets/icons8-map-marker-64.png')
              }
              style={{ width: 30, height: 30 }}
            />
          </TouchableOpacity>
        </Marker>
      );
    },
    (prevProps, nextProps) => {
      // Only re-render when isActive changes
      return prevProps.isActive === nextProps.isActive;
    }
  );

re-render only when the isActive property changes.

Upvotes: 0

Related Questions