Leaflet cluster marker re-renders and closes open spider even though data was not changed

Viewed 652

I have a Leaflet map in a react app, and I'm using react-leaflet-markercluster in order to cluster markers that are on the exact same coordinates.

I also have a request I make every 5 seconds to get the markers, mostly they are the same markers, but still, when clicking on a cluster marker, after that 5 seconds, all markers are re-rendered, and the spider closes.

You can try and see it in this demo (click and wait, the spider closes): https://stackblitz.com/edit/cluster-keeps-rerendering

Does anyone have an idea of how this can be solved?

1 Answers

This is expected behavior since in your example a deep copy of markers array is getting created:

   this.setState(prevState => ({
        markers: prevState.markers.map(marker => ([ ...marker ]))
      }));

From shouldComponentUpdate documentation:

PureComponent performs a shallow comparison of props and state, and reduces the chance that you’ll skip a necessary update.

meaning every time when markers state changes Map component gets re-rendered.

Consider to create a shallow copy of markers array instead, for example:

const newMarkers = [...this.state.markers];
this.setState(prevState => ({
    markers: newMarkers
}));

or perform a custom comparison via shouldComponentUpdate lifecycle method, the following example demonstrates how to prevent MarkerClusterGroup from re-rendering by comparing if markers coordinates have changed:

class MarkerList extends React.Component {

  shouldComponentUpdate(nextProps, nextState) { 
      const markers = nextProps.markers.filter((m, i) => this.props.markers[i][0] !== m[0] || this.props.markers[i][1] !== m[1]); 

     return markers.length > 0;
  } 

  render() {
    return (
        <MarkerClusterGroup
          showCoverageOnHover={false}
          maxClusterRadius={0}
        >
          {this.props.markers.map((marker, index) => (
            <Marker position={marker} key={index} />
          ))}
        </MarkerClusterGroup>
    );
  }
}  

Here is a forked example

Note

This approach is usually not recommended since might lead to bugs and React documentation says the following in this regard:

We do not recommend doing deep equality checks or using JSON.stringify() in shouldComponentUpdate(). It is very inefficient and will harm performance.

Related