首页 > 解决方案 > 尝试在 react-google-maps 上卸载 4k+ 标记时冻结浏览器

问题描述

我正在构建一个 React 应用程序,其中许多标记显示在 react-google-maps 地图上。用户可以过滤标记,以便不会一次显示所有标记。使用 MarkerClusterer 显示 4000 个标记可以正常工作。显示它们需要相当长的时间,并且地图随后会做出响应。

现在,当我在之前渲染 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);

在选择某些内容后,我确保显示标记具有正确的值(在这种情况下,显示标记从 4000 个条目变为 1 个)。我逐步检查了整个应用程序,以确保在发生这种不幸行为时我计算的每个值都是正确的。此外,在冻结之前不会再次调用渲染方法。从 4000 显示的标记更改为 3999 或 3980 可以正常工作。

为了更好地了解应用程序,我制作了一个 CodeSandbox(它不呈现任何内容,因为缺少 api 密钥和数据):https ://codesandbox.io/s/v830m9p7ry?fontsize=14&view=editor

我是 react 和 redux 的新手,我真的不知道接下来我应该测试什么或做什么来找出为什么会发生这种情况。

提前感谢您的帮助!

编辑:添加了性能分析。这也是 在性能分析中的 30 秒标记之后显示的。它正在渲染每个标记,并一个一个地删除它们。

标签: javascriptgoogle-mapsreact-reduxgoogle-maps-markersreact-google-maps

解决方案


推荐阅读