MarkerCluster
コンテキスト初期化からリーフレットマップを使用して再利用可能なコンポーネントを作成し、ネストされたマップコンポーネントを更新したいと思います。MyMap
から動的アクションを実行するためにコンポーネントに直接埋め込む必要はありませんreact-router
が、ネストされたマーカーMarkerCluster
がshouldComponentUpdate === false
更新されない場合。この問題はissueに関連している可能性があることがわかりましたが、私の場合、これを回避する方法が見つかりませんでした。shouldComponentUpdate を true に設定するだけでなく、より良い解決策があると今でも信じています。私の 2 つの例の動作の違いを説明していただけますか? それとも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>