Замораживание браузера при попытке размонтировать маркеры 4k + на реагирующих google-картах - PullRequest
0 голосов
/ 07 марта 2019

Я создаю приложение React, в котором многие маркеры отображаются на карте реагировать-google-maps. Пользователь может фильтровать маркеры так, чтобы не все отображались одновременно. Отображение 4000 маркеров с помощью MarkerClusterer работает нормально. Для их отображения требуется разумное количество времени, а затем карта отзывчива.

Моя проблема теперь возникает, когда я пытаюсь отобразить только один или несколько маркеров после того, как рендерил 4000 раньше. Браузер зависает, и я больше ничего не могу сделать в браузере. Нет предупреждения или ошибки бесконечного цикла. Консоль не отображает ничего, что могло бы помочь мне до остановки.

Код для отображения компонента карты:

import React from 'react';
import { compose, withProps, withHandlers } from "recompose"
import { withScriptjs, withGoogleMap, GoogleMap, TrafficLayer } from "react-google-maps"
import { connect } from 'react-redux';

import MarkersList from './MarkersList';

const { MarkerClusterer } = require("react-google-maps/lib/components/addons/MarkerClusterer");

const Map = compose(
    withProps({
      googleMapURL: "https://maps.googleapis.com/maps/api/js?key=*******&callback=initMap",
      loadingElement: <div style={{ height: `100%` }} />,
      containerElement: <div style={{ height: `100vh` }} />,
      mapElement: <div style={{ height: `100%` }} />
    }),
    withHandlers({
      onMarkerClustererClick: () => (markerClusterer) => {
        const clickedMarkers = markerClusterer.getMarkers()
        console.log(`Current clicked markers length: ${clickedMarkers.length}`)
        console.log(clickedMarkers)
      }
    }),
    withScriptjs,
    withGoogleMap
  )((props) => 
       <GoogleMap
            defaultZoom={5.76}
            defaultCenter={{ lat: 49.4299758, lng: 14.0531568 }}
            mapTypeId="terrain"
            fullscreenControl={false}
            >
              <TrafficLayer autoUpdate />
              <MarkerClusterer
                onClick={props.onMarkerClustererClick}
                averageCenter
                enableRetinalIcons
                gridSize={60}
                >
                  {props.isMarkerShown && <MarkersList/>}
                </MarkerClusterer>
        </GoogleMap>

);

export default connect()(Map);

Компонент MarkersList:

import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Marker, InfoWindow } from 'react-google-maps';

import { markersActionCreators } from './MarkersActions';

class MarkersList extends React.Component {
    componentDidMount() {
        if(this.props.markers.length === 0) {
            this.props.requestMarkers();
        }
    }

    render() {
        var listComponent = this.props.displayedMarkers.map((marker, index) => 
                <Marker 
                    key={index}
                    position={{lat: marker.currentPositionLat, lng: marker.currentPositionLng}} 
                    onClick={() => this.props.onToggleOpen(index)} 
                    tracksViewChanges={false}
                >
                    {this.props.isOpen && this.props.infoIndex === index &&
                    <InfoWindow onCloseClick={() => this.props.onToggleOpen(index)}>
                        <div>
                            <h6>Truck Id: {marker.vehicleName}</h6>
                            <b>Registration Plate: {marker.registrationNumber}</b>
                            <br/>
                            <p>
                                Position recorded on <i>{marker.time}</i> <br/>
                                Engine is [{marker.currentIgnitionState}] <br/>
                                Fuel Level: {marker.currentFuelLevel} L left <br/>
                                Speed: {marker.currentSpeed} Km/h <br/>
                            </p>

                        </div>
                    </InfoWindow>}
                </Marker>
            );
        return <div>{listComponent}</div>;
    }
};

export default connect(
    state => state.mainArea.markersReducer,
    dispatch => bindActionCreators(markersActionCreators, dispatch)
  )(MarkersList);

Я гарантировал, что displayMarkers имеет правильное значение после выбора чего-либо (в этом случае displayMarkers изменяется с 4000 записей на 1). Я прошелся по всему приложению, чтобы убедиться, что каждое вычисленное мной значение верно, когда происходит такое неудачное поведение. Кроме того, метод рендеринга не вызывается второй раз перед остановкой. Изменение с 4000 отображаемых маркеров на 3999 или 3980 работает должным образом.

Для лучшего обзора приложения я создал CodeSandbox (он ничего не отображает, потому что отсутствует ключ API и данные): https://codesandbox.io/s/v830m9p7ry?fontsize=14&view=editor

Я новичок в реагировании и редукции, и я действительно не знаю, что мне следует проверить или сделать дальше, чтобы выяснить, почему это происходит.

Заранее спасибо за любую помощь!

РЕДАКТИРОВАТЬ: Добавлен анализ производительности . А также отображается после 30-секундной отметки в анализе производительности . Он рендерит каждый маркер и удаляет их один за другим.

...