Я хотел бы создать многоразовый компонент MarkerCluster
с карточкой листовки из контекста, инициализировать его один раз, а затем предоставлять обновления на вложенных компонентах карты. Мне нужно встроить его непосредственно в компонент MyMap
для выполнения динамических действий с react-router
, но когда MarkerCluster
имеет shouldComponentUpdate === false
, тогда вложенные маркеры не будут обновляться. Я обнаружил, что эта проблема может быть связана с issue, но я не нашел, как это сделать в моем случае. Я все еще верю, что есть лучшее решение, чем просто установить toComponentUpdate в 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()
\t const initialState = [
\t {position: [51.5, -0.1]},
\t {position: [51.51, -0.1]},
\t {position: [51.49, -0.05]},
\t ]
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() {
\t 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/[email protected]/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()
\t const initialState = [
\t {position: [51.5, -0.1]},
\t {position: [51.51, -0.1]},
\t {position: [51.49, -0.05]},
\t ]
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() {
\t 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/[email protected]/dist/react-leaflet.js"></script>
<div id="container"></div>
Это не то, для чего используется компонентShouldUpdate. Вы сказали, что он не обновляется, и теперь он не обновляется. Если вы хотите, чтобы он обновлялся, тогда не устанавливайте этот крючок таким образом. – gravityplanx
Итак, почему второй пример работает? – luzny
It ** - ** рабочий.Вы сказали, что не обновлять, а не обновлять. Если вы хотите его обновить, не устанавливайте эту функцию для возврата 'false'. – gravityplanx