我想MarkerCluster
从上下文初始化一次创建带有传单地图的可重用组件,然后提供嵌套地图组件的更新。我需要将它不直接嵌入到MyMap
组件中以执行动态操作react-router
,但是嵌套标记MarkerCluster
何时shouldComponentUpdate === false
不会更新。我发现这个问题可能与问题有关,但在我的情况下我没有找到解决这个问题的方法。我仍然相信有比将 shouldComponentUpdate 设置为 true 更好的解决方案。你能解释一下我的两个例子之间的行为差异吗?或者,MarkerCluster
以 React 方式构建没有上下文的可重用组件是否是一个更好的解决方案?
演示:
const React = window.React;
const { Map, TileLayer, Marker, MapLayer, PropTypes } = window.ReactLeaflet;
const { markerClusterGroup } = window.L;
class MarkerCluster extends MapLayer {
static childContextTypes = {
layerContainer: PropTypes.layerContainer
};
getChildContext () {
return {
layerContainer: this.leafletElement
}
}
componentWillMount () {
super.componentWillMount()
this.leafletElement = markerClusterGroup()
}
shouldComponentUpdate () {
return false
}
render () {
console.log("update markers cluster")
return <div style={{display: 'none'}}>{this.props.children}</div>
}
}
class MapMarkers extends React.Component {
constructor () {
super()
const initialState = [
{position: [51.5, -0.1]},
{position: [51.51, -0.1]},
{position: [51.49, -0.05]},
]
this.state = {markers: initialState};
}
componentDidMount() {
setInterval(this.addMarker.bind(this), 3000);
}
addMarker() {
const lat = (Math.random() * (51.49 - 51.51) + 51.51);
const lng = (Math.random() * (0.05 - 0.1) - 0.1);
const marker = {position: [lat, lng]};
this.setState({markers: this.state.markers.concat([marker])});
}
render() {
console.log("update markers")
const markers = this.state.markers.map((item, key) =>
<Marker position={item.position} key={key} />
);
return <MarkerCluster>{markers}</MarkerCluster>;
}
}
class MyMap extends React.Component {
render() {
return (
<Map center={[51.50, -0.1]} zoom={13}>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
{this.props.children}
</Map>
)
}
}
class MainLayout extends React.Component {
render() {
return (
<MyMap>
<MapMarkers />
</MyMap>
)
}
}
window.ReactDOM.render(<MainLayout />, document.getElementById('container'));
.leaflet-container {
height: 400px;
width: 100%;
}
<link href="https://rawgit.com/Leaflet/Leaflet.markercluster/leaflet-0.7/dist/MarkerCluster.Default.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.js"></script>
<script src="https://rawgit.com/Leaflet/Leaflet.markercluster/leaflet-0.7/dist/leaflet.markercluster.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://npmcdn.com/react-leaflet@0.12.2/dist/react-leaflet.js"></script>
<div id="container"></div>
为什么下面的示例有效,而上面的示例无效?
const React = window.React;
const { Map, TileLayer, Marker, MapLayer, PropTypes } = window.ReactLeaflet;
const { markerClusterGroup } = window.L;
class MarkerCluster extends MapLayer {
static childContextTypes = {
layerContainer: PropTypes.layerContainer
};
getChildContext () {
return {
layerContainer: this.leafletElement
}
}
componentWillMount () {
super.componentWillMount()
this.leafletElement = markerClusterGroup()
}
shouldComponentUpdate () {
return false
}
render () {
console.log('update markers cluster')
return <div style={{display: 'none'}}>{this.props.children}</div>
}
}
class MapMarkers extends React.Component {
constructor () {
super()
const initialState = [
{position: [51.5, -0.1]},
{position: [51.51, -0.1]},
{position: [51.49, -0.05]},
]
this.state = {markers: initialState};
}
componentDidMount() {
setInterval(this.addMarker.bind(this), 3000);
}
addMarker() {
const lat = (Math.random() * (51.49 - 51.51) + 51.51);
const lng = (Math.random() * (0.05 - 0.1) - 0.1);
const marker = {position: [lat, lng]};
this.setState({markers: this.state.markers.concat([marker])});
}
render() {
console.log('update markers')
const markers = this.state.markers.map((item, key) =>
<Marker position={item.position} key={key} />
);
return <div>{markers}</div>;
}
}
class MyMap extends React.Component {
render() {
return (
<Map center={[51.50, -0.1]} zoom={13}>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
<MarkerCluster><MapMarkers /></MarkerCluster>
</Map>
)
}
}
class MainLayout extends React.Component {
render() {
return (
<MyMap />
)
}
}
window.ReactDOM.render(<MainLayout />, document.getElementById('container'));
.leaflet-container {
height: 400px;
width: 100%;
}
<link href="https://rawgit.com/Leaflet/Leaflet.markercluster/leaflet-0.7/dist/MarkerCluster.Default.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.js"></script>
<script src="https://rawgit.com/Leaflet/Leaflet.markercluster/leaflet-0.7/dist/leaflet.markercluster.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://npmcdn.com/react-leaflet@0.12.2/dist/react-leaflet.js"></script>
<div id="container"></div>