【问题标题】:react list + map component反应列表+地图组件
【发布时间】:2016-06-04 10:42:32
【问题描述】:

我正在做一个反应项目,我想要实现的是一个项目列表,旁边有一个谷歌地图。我已经研究了很长时间,寻找最好的方法,我发现了很多例子,但它们并没有真正的表现。 我还希望当您在列表的某个项目上时,地图中相应项目的标记会更改颜色或类似的东西,所以我想将标记与列表中的项目同步。

这是我的地图组件,让您知道我目前正在使用哪些库:

import React from 'react';
import GoogleMaps from 'google-maps-api';
import MapConfig from 'config/maps.json';
import mapStyles from './map.styles';

const MapWithKey = GoogleMaps(MapConfig.API_KEY);

class Map extends React.Component {

    render() {
        const items = this.props.items;
        MapWithKey().then(( maps ) => {
            const map = new maps.Map(document.getElementById('js-map'), {
                center: {lat: -34.397, lng: 150.644},
                scrollwheel: false,
                zoom: 8,
                mapTypeControl: false,
                streetViewControl: false
            });

            for ( let item of items ) {
                new maps.Marker({
                    position: new maps.LatLng(item.latitude, item.longitude),
                    map: map
                });
            }
        });


        return(
            <div style={mapStyles} id="js-map">{this.props.children}</div>
        );
    }
}

export default Map;

我注意到在开发过程中我无法在状态中添加标记,因为每次添加标记时,组件都会重新渲染。

您知道这样做的好方法并以好的方式构建组件吗? 非常感谢您的帮助。

提前致谢。

【问题讨论】:

    标签: google-maps google-maps-api-3 reactjs google-maps-markers


    【解决方案1】:

    听起来像是shouldComponentUpdate 的工作。

    此生命周期方法允许您决定是否应在每次更新状态或道具时重新渲染组件。

    shouldComponentUpdate() {
      return false;
    }
    

    现在您可以安全地将标记存储在 this.state 中并使用命令式 Maps API 更新它们,而不必担心您的组件会尝试重新渲染。

    还值得一提的是shouldComponentUpdate 不会影响初始渲染,您仍然可以使用forceUpdate 强制更新。

    您可能还需要考虑重组您的组件以遵循一些最佳实践。您可以使用带有回调的 ref 属性来获取对 DOM 元素的引用,而无需 id

    return(
      <div style={mapStyles} ref={containerMounted}>{this.props.children}</div>
    );
    

    然后您可以将您的初始化逻辑移动到新的containerMounted 方法中。

    containerMounted(container) {
      MapWithKey().then(( maps ) => {
        const map = new maps.Map(container, {
          // ...
        });
    
        // save a reference to map for later
        this.setState({ map });
      });
    }
    

    最后,重要的是您的标记在道具更改时重新渲染。以前我们可以在 render 函数中完成此操作。您看到性能不佳的部分原因是您每次调用渲染时都在创建新标记。相反,您需要移动现有的。

    // create the markers before initial render
    componentWillMount() {
      this.createMarkers(this.props.items);
    }
    
    // recreate the markers only when props changes
    componentWillReceiveProps(nextProps) {
      if(nextProps.items === this.props.items) return;
      this.removeMarkers(this.state.markers);
      this.createMarkers(nextProps.items);
    }
    
    // remove a list of markers from the map
    removeMarkers(markers) {
      markers.forEach(m => m.setMap(null));
    }
    
    // create a list of markers on the current map
    createMarkers(items) {
      const markers = items.map(item => {
        return new maps.Marker({
          position: new maps.LatLng(item.latitude, item.longitude),
          map: this.state.map
        });
      });
    }
    

    【讨论】:

    • 你太棒了!!!这么好的答案,只有一件事......在 componentWillReceiveProps 中您使用 this.state.markers 之前没有设置它,我猜它在 createMarkers 中创建标记集合,对吗?
    • 还有一件事,映射对象,从 GMaps 返回承诺的对象只能在 containerMounted 中访问,我试图将它设置为类的状态或属性,但由于它是一个承诺,它是需要时不可用
    • 是的,您可能需要一个 getInitialState 方法来返回标记的初始版本。是的,如果你想使用mapsmap 对象,你需要以同样的方式公开它。
    • 我试图将它暴露给状态,但由于它是一个承诺,它在第一次渲染之后出现,所以它是未定义的:(
    • 在组件上也暴露promise,然后你可以为它创建多个监听器。
    猜你喜欢
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 2019-03-20
    • 2019-07-22
    • 2023-04-03
    • 2018-02-14
    • 2019-04-24
    • 2021-05-31
    相关资源
    最近更新 更多