2016-09-18 2 views
2

リテレットマップを持つ再利用可能なMarkerClusterコンポーネントをコンテキストinitから作成してから、ネストされたマップコンポーネントの更新を提供したいと考えています。 react-routerから動的アクションを実行するには、MyMapコンポーネントに直接埋め込む必要はありませんが、MarkerClustershouldComponentUpdate === falseがある場合、ネストされたマーカーは更新されません。この問題はissueに関連する可能性があることがわかりましたが、私の場合はこれを回避する方法が見つかりませんでした。私はまだshouldComponentUpdateをtrueに設定するよりも優れたソリューションがあると考えています。私の2つの例の間の行動の違いを説明できますか?それとも、再利用可能なMarkerClusterコンポーネントを、リアクションの方法でコンテキストなしで構築する方がよいでしょうか?埋め込みコンポーネントの親からコンテキストを一度適用し、子を更新する方法は?

デモ:

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='&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() { 
 
    \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='&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() { 
 
    \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>

+2

これは、componentShouldUpdateが使用されるものではありません。あなたは更新しないように言いましたが、今は更新していません。それを更新したい場合は、そのようにフックを設定しないでください。 – gravityplanx

+0

なぜ2番目の例が効果的なのですか? – luzny

+0

**は**働いています。あなたは更新しないように指示し、更新していません。更新したい場合は、その関数を 'false'を返すように設定しないでください。 – gravityplanx

答えて

0

私はあなたがそれを行うだろう、なぜ知りません。 反応の仕組みと調整プロセスの仕組みを最初に理解する必要があります。あなたが広いshouldComponentUpdateについての説明とどのようにそれを適切に使用するなど、高度なprefomance、読むことができ https://facebook.github.io/react/docs/reconciliation.html

そして、ここで:

https://facebook.github.io/react/docs/advanced-performance.html

はこちらをご覧ください、このプロセスを説明します

うまくいけば、あなたがこれを読んだ後、あなたが望むものがなぜ不可能であるかを理解するでしょう。 いずれにしても、調整プロセスですべてのネストされたコンポーネントをスキップするため、shouldComponentUpdateを実装することは決してfalseを返すべきではありません。

0

は、クラスタリングマーカーの最小・軽量のラッパーですreact-leaflet-markercluster

の実装を確認してください。

出典:src/react-leaflet-markercluster.js

1)ラッパーが反応-リーフレット画層グループを拡張:

import 'leaflet.markercluster'; 

let markerClusterGroup = L.markerClusterGroup(this.props.options); 

3:新しいmarkerClusterGroup、すべてのマーカーがクラスタ化されるグループを作成

import {LayerGroup} from 'react-leaflet'; 

export default class MarkerClusterGroup extends LayerGroup { 
    ... 

2) )layerContainer(layerContainerは、反応リーフレットを拡張するMarkerClusterGroupコンポーネントが使用可能なため、マーカーとしてmarkerClusterGroupをレイヤーとしてマップに追加します。 LayerGroup)

this.layerContainer.addLayer(markerClusterGroup); 
関連する問題