javascript - 尝试在 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 秒标记之后显示的。它正在渲染每个标记,并一个一个地删除它们。
解决方案
推荐阅读
- c - 如何测量libuv中的延迟?
- node.js - react native 中的密码重置不起作用
- r - 如何在 R 中碱基对图的空白空间中添加图例?
- visual-studio-2019 - Visual Studio 2019 调试观察窗口
- javascript - 传入新道具时,如何将组件的状态重置为默认值?
- reactjs - React - UseState,UseRef..In Trouble
- python - 从 ul 类中获取所有元素并与文本文件进行比较(Python Selenium)
- php - 如何在 php 文件(wordpress)中显示自定义模板?
- sql-server - 优化海量数据查询
- svg - d3.js - 从边框到边框绘制箭头线