为啥要在标记点击事件上重新渲染地图?
Posted
技术标签:
【中文标题】为啥要在标记点击事件上重新渲染地图?【英文标题】:Why map re rendering on marker click event?为什么要在标记点击事件上重新渲染地图? 【发布时间】:2019-10-03 08:18:55 【问题描述】:我有带有集群的多个标记的谷歌地图。单击标记时,我会显示信息窗口,但是当我单击标记时,整个地图标记和集群都会重新渲染,这会使页面变慢且令人讨厌。
以下是我的代码:
import React, Component from "react";
import axios from "axios";
import compose, withProps, withHandlers, withStateHandlers from "recompose";
import
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
from "react-google-maps";
const
MarkerClusterer
= require("react-google-maps/lib/components/addons/MarkerClusterer");
const MapWithAMarkerClusterer = compose(
withProps(
googleMapURL:
"https://maps.googleapis.com/maps/api/js?key=API&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style= height: `100%` />,
containerElement: <div style= height: `90vh` />,
mapElement: <div style= height: `100%` />
),
withStateHandlers(
InfoWindowobject: null ,
setInfoWindow: () => value => ( InfoWindowobject: value )
),
withStateHandlers(
isOpen: false ,
onToggleOpen: ( isOpen ) => () => (
isOpen: !isOpen
)
),
withHandlers(
onMarkerClustererClick: () => markerClusterer =>
const clickedMarkers = markerClusterer.getMarkers();
,
onMarkerClick: props => markerss =>
const setInfoWindow, onToggleOpen = props;
axios(
url: "API",
method: "POST",
).then(res =>
setInfoWindow(res.data);
onToggleOpen();
);
),
withScriptjs,
withGoogleMap
)(props => (
<GoogleMap
defaultZoom=5
defaultCenter= lat: 22.845625996700075, lng: 78.9629
>
<MarkerClusterer
onClick=props.onMarkerClustererClick
minimumClusterSize=10
averageCenter
styles=[
textColor: "white",
url: imgmapcluster,
height: 68,
lineHeight: 3,
width: 70
]
enableRetinaIcons
gridSize=60
>
props.markers.map((marker, index) => (
<Marker
key=index
icon=user
onClick=props.onMarkerClick.bind(props, marker)
position= lat: marker.latitude, lng: marker.longitude
/>
))
props.isOpen && props.InfoWindowobject !== null && (
<InfoWindow
position=
lat: props.InfoWindowobject.latitude,
lng: props.InfoWindowobject.longitude
onCloseClick=props.onToggleOpen
>
props.InfoWindowobject !== null && (
<div className="infobox clearfix" style= fontFamily: "Gotham" >
<div className="header clearfix">
<h3>
props.InfoWindowobject.name," "
<small>props.InfoWindowobject.contactNo</small>
</h3>
</div>
</div>
)
</InfoWindow>
)
</MarkerClusterer>
</GoogleMap>
));
class DemoApp extends React.PureComponent
componentWillMount()
this.setState( markers: [], isOpen: false, InfoWindowobject: );
componentDidMount()
axios(
url: "API",
).then(res =>
this.setState( markers: res.data.data.list );
);
render()
return (
<MapWithAMarkerClusterer
markers=this.state.markers
isOpen=this.state.isOpen
InfoWindowobject=this.state.InfoWindowobject
/>
);
参考: https://tomchentw.github.io/react-google-maps/#markerclusterer
【问题讨论】:
【参考方案1】:这是一种预期行为,因为每次状态更改都会重新渲染。
为了防止重新渲染,你可以考虑用 shouldUpdate
higher-order component 包裹 MarkerClusterer
组件,让 React 知道组件是否应该受到更改状态的影响,如下所示:
const MyMarkerClusterer = shouldUpdate(checkPropsChange)(props =>
const onMarkerClick,markers,...clusterProps = props;
return (
<MarkerClusterer
...clusterProps
>
markers.map(marker => (
<Marker
key=marker.photo_id
position= lat: marker.latitude, lng: marker.longitude
onClick=onMarkerClick.bind(this, marker)
/>
))
</MarkerClusterer>
);
);
在哪里
const checkPropsChange = (props, nextProps) =>
return nextProps.markers.length !== props.markers.length; //re-render only if markers prop changed
;
Here is a demo
【讨论】:
【参考方案2】:onMarkerClick
调用 API 和(获取后)两个处理程序:setInfoWindow()
,'onToggleOpen`。
两个处理程序都会调用带有状态更改的结果并强制重新呈现嵌入组件 (<GoogleMap/>
)。
您应该使用处理程序嵌入<MarkerClusterer/>
,并将这个增强的组件作为子组件传递给<GoogleMap/>
组件(或简单地在内部渲染)。
【讨论】:
以上是关于为啥要在标记点击事件上重新渲染地图?的主要内容,如果未能解决你的问题,请参考以下文章