【问题标题】:Infowindow re rendering whole google map with thousands of marker everytimeInfowindow 每次都用数千个标记重新渲染整个谷歌地图
【发布时间】:2019-06-03 23:24:28
【问题描述】:

所以,我是新来的反应并尝试在 google-maps-react 中添加标记及其信息窗口。另外,我从 API 获得了数千个标记位置。

每次单击标记并打开其相关信息窗口时,它都会再次渲染整个数千个标记,这既费时又不那么有趣。

  import React, { Component } from 'react';
  import { Map, InfoWindow, Marker, GoogleApiWrapper } from 'google-maps-react';
  import DRINKING_WATER_PUMP from './pins/Drinking_RMS_Absent.png'
  import ROOFTOP from './pins/Rooftop_RMS_Absent.png'
  import IRRIGATION_PUMP from './pins/Irrigation_RMS_Absent.png'
  import PATVAN from './pins/Patvan_RMS_Absent.png'
  import MINIGRID from './pins/Minigrid_RMS_Absent.png'
  import farmer from './pins/CCAFS-image.png'
  const mapStyles = {
    width: '100%',
    height: '100%',
    position:'relative',
    display: 'flex', 
    flexFlow: 'row nowrap', 
    justifyContent: 'center',
  };
  export class MapContainer extends Component {
    constructor(props){
        super(props)
        this.state = {
          showingInfoWindow: false,  //Hides or the shows the infoWindow
          activeMarker: {},          //Shows the active marker upon click
          selectedPlace: {}          //Shows the infoWindow to the selected place upon a marker
        };
        this.onMarkerClick=this.onMarkerClick.bind(this)
        this.onClose=this.onClose.bind(this)
      }
    onMarkerClick(props, marker, e){
      console.log('on click called:')
      this.setState({
      selectedPlace: props,
      activeMarker: marker,
      showingInfoWindow: true
      });
    }
    onClose(props) {
      if (this.state.showingInfoWindow) {
        this.setState({
          showingInfoWindow: false,
          activeMarker: null
        });
      }
    }
    render() {
      console.log('render')
      return (
        <Map id="map"
          mapTypeControl={false}
          gestureHandling= {'greedy'}
          zoomControl= {false}
          streetViewControl={false}
          fullscreenControl={false}
          google={this.props.google}
          zoom={5}
          style={mapStyles}
          initialCenter={{
           lat: 21.5937,
           lng: 78.9629
          }}
        >
          {
            this.props.datapins.map((marker, index) => {
              let assetType=marker.assetType
              let icon={
              url:'' ,
              anchor: new this.props.google.maps.Point(12,23),
              origin: new this.props.google.maps.Point(0,0),
              scaledSize:  new this.props.google.maps.Size(20,20)
              }
              switch(assetType){
                case 'PATVAN':icon.url=PATVAN; break;
                case 'MINIGRID':icon.url=MINIGRID; break;
                case 'IRRIGATION_PUMP':icon.url=IRRIGATION_PUMP; break;
                case 'DRINKING_WATER_PUMP':icon.url=DRINKING_WATER_PUMP; break;
                case 'ROOFTOP':icon.url=ROOFTOP; break;
                default: break;
              }
              return (
              <Marker key={index} icon={icon} position={{lat: parseFloat(marker.lat), lng: parseFloat(marker.lng)}} onClick={this.onMarkerClick}  />
              )
            })
          }
          <InfoWindow className="infoWindowCard"
            pixelOffset={new this.props.google.maps.Size(170,380)}
            marker={this.state.activeMarker}
            visible={this.state.showingInfoWindow}
            onClose={this.onClose}
          >
            <div style={{'overflow':'hidden'}}>
              <img src={farmer} alt='farmer' className="infoWindowImg"/>
              <h4 className="infoWindowName"> Satpal Singh </h4>
              <h6 className="infoWindowName"> Customer ID: 007 </h6>
              <div>
              <ul className="infoWindowDetail">
                <li>
                  <div className="row">
                    <div className="col-md-2">
                      <i className="fa fa-calendar" aria-hidden="true"></i>
                    </div>
                    <div className="col-md-10">
                    <span>Installed on 02 Dec 2017</span>
                    </div>
                  </div>
                </li>
                <li>
                  <div className="row">
                    <div className="col-md-2">
                      <i className="fa fa-map-marker" aria-hidden="true"></i>
                    </div>
                    <div className="col-md-10">
                    <span>Chuni ka Pura</span>
                    <p>Morena, Madhya pradesh </p>
                    </div>
                  </div>
                </li>
                <li>
                  <div className="row">
                    <div className="col-md-2">
                      <i className="fa fa-tint" aria-hidden="true"></i>
                    </div>
                    <div className="col-md-10">
                    <span>Irrigation Pump <b>2HP AC Surface</b></span>
                    <p>Solar Panel Capacity 300Wp </p>
                    </div>
                  </div>
                </li>
              </ul>
              <div className="portal">
                <span>Visit portal</span><a href="/"><i className="fa fa-external-link-square" aria-hidden="true"></i></a>
              </div>
              </div>
            </div>
          </InfoWindow>
        </Map>
      );
    }
  }

  export default GoogleApiWrapper({
    apiKey: 'MYAPI'
  })(MapContainer);

下面是屏幕图像,可帮助您了解我正在添加的引脚以及为什么它是标记信息窗口加载缓慢的原因。

Map with pins

那么,我该如何解决上述耗时渲染的问题? 将不胜感激。谢谢

【问题讨论】:

    标签: reactjs google-maps


    【解决方案1】:

    为了防止这种行为,可以引入以下标记组件:

    class MarkersList extends React.Component {
    
      constructor(props) {
        super(props);
        this.markersRendered = false;
      }
    
      shouldComponentUpdate(nextProps, nextState) {
        if (JSON.stringify(this.props.places) === JSON.stringify(nextProps.places) && this.markersRendered) {
          return false;
        }
        this.markersRendered = true;
        return true;
      }
    
      render() {
        return (
          <span>
            {this.props.places.map((place, i) => {
              return (
                <Marker
                  {...this.props}
                  key={i}
                  data={place}
                  position={{ lat: place.lat, lng: place.lng }}
                />
              );
            })}
          </span>
        )
      }
    
    }
    

    如果标记数据尚未更新,则会阻止重新渲染标记 (shouldComponentUpdate method)

    这里是a demo

    【讨论】:

    • 您的上述代码中有一个错误。如果单击标记,关闭信息窗口并再次单击相同的标记,您将不会再次看到信息窗口
    • 还包括以下解决了这个问题:onClose={this.onInfoWindowClose}
    • 我面临与您完全相同的问题。我做了你的改变,它正在工作!谢谢。但是我面临的一个问题是:当我刷新网页(在localhost:3000 上运行)时,“markersRendered”标志以某种方式变为“true”并且页面刷新时没有显示任何标记。为什么?任何想法?注意:这个类的构造函数被调用使得这个标志为假,但不知道为什么这个标志转换为真,后记。
    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 2011-11-16
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 2023-03-28
    • 2018-11-16
    相关资源
    最近更新 更多