2

MarkerClusterコンテキスト初期化からリーフレットマップを使用して再利用可能なコンポーネントを作成し、ネストされたマップコンポーネントを更新したいと思います。MyMapから動的アクションを実行するためにコンポーネントに直接埋め込む必要はありませんreact-routerが、ネストされたマーカーMarkerClustershouldComponentUpdate === 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='&copy; <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='&copy; <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>

4

2 に答える 2