Маркер кластера листовки повторно отображает и закрывает открытый паук, даже если данные не были изменены

#reactjs #react-leaflet #leaflet.markercluster

#reactjs #react-листовка #leaflet.markercluster

Вопрос:

У меня есть Leaflet карта в приложении react, и я использую react-leaflet-markercluster ее для кластеризации маркеров, которые находятся в одних и тех же координатах.

У меня также есть запрос, который я делаю каждые 5 секунд, чтобы получить маркеры, в основном это одни и те же маркеры, но все же, при нажатии на маркер кластера, по истечении этих 5 секунд все маркеры повторно отображаются, и паук закрывается.

Вы можете попробовать и увидеть это в этой демонстрации (нажмите и подождите, паук закроется): https://stackblitz.com/edit/cluster-keeps-rerendering

У кого-нибудь есть представление о том, как это можно решить?

Ответ №1:

Это ожидаемое поведение, поскольку в вашем примере создается глубокая копия markers массива:

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

Из shouldComponentUpdate документации:

PureComponent выполняет поверхностное сравнение реквизитов и состояния и снижает вероятность того, что вы пропустите необходимое обновление.

это означает, что каждый раз, когда markers изменяется состояние Map , компонент повторно отображается.

Подумайте о том, чтобы вместо этого создать мелкую копию markers массива, например:

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

или выполните пользовательское сравнение с помощью shouldComponentUpdate метода жизненного цикла, следующий пример демонстрирует MarkerClusterGroup , как предотвратить повторную визуализацию путем сравнения, если markers координаты изменились:

 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>
    );
  }
}  
  

Вот разветвленный пример

Примечание

Этот подход обычно не рекомендуется, поскольку может привести к ошибкам, и в документации React по этому поводу говорится следующее:

Мы не рекомендуем выполнять глубокие проверки на равенство или использовать JSON.stringify() в shouldComponentUpdate() . Это очень неэффективно и повредит производительности.