【问题标题】:ReactJS and Google Maps - Displaying MarkersReactJS 和谷歌地图 - 显示标记
【发布时间】:2020-07-09 18:22:28
【问题描述】:

我是 React 新手,所以可能会问一个愚蠢的问题,但这让我感到困惑。作为学习的一部分,我正在构建一个三组件应用程序 - 一个父级 About 和两个子级(GoogleMapMapMarkerDetails)。父母进行数据协调,一个孩子默认显示带有两个标记的谷歌地图,另一个孩子在点击时显示标记的详细信息。

我现在正在添加功能以在单击地图时添加新标记。大多数功能都有效 - 绘制地图,添加默认标记,当单击其中一个标记时,这会调用父类上的一个函数来更新其状态,并将其传播到 MapMarkerDetails 元素和显示简单的消息。

这是我为帮助理解而评论的父类:

import React, { Component } from 'react';
import GoogleMap from './GoogleMap'
import MapMarkerDetails from './MapMarkerDetails'

class About extends Component {

state = {
    markers: [{
        position: { lat: 51.438759, lng: -2.864514 },
        label: 'A',
        map: null,
    }, {
        position: { lat: 51.433636, lng: -2.868734 },
        label: 'B',
        map: null,
    }],
    greeting: 'HelloA'
}

showMarkerInfo = (label) => {
    this.setState({greeting: ('Hello ' + label)})
}

/* 
Adding a new Marker 
This function is called from the child element GoogleMap
However, the setState(...) dosn't seem to propogate down to the GoogleMap element.
*/
addMarker = (latlng) => {
    let newMarker = [{
        position: { lat: latlng.lat(), lng: latlng.lng() },
        label: 'New',
        map: null,
    }];

    /* Creates a new array for updating state. Is this the best way to do this */
    let markers = [...this.state.markers, ...newMarker] 
    this.setState({markers});

    console.log(this.state) // This shows the added marker
}

render() {
    return (
        <div className="container">
            <h4 className="center">About</h4>
            <MapMarkerDetails details={this.state.greeting}/>
            <GoogleMap markers={this.state.markers} clickedMarker={this.showMarkerInfo} addMarker={this.addMarker}/>
        </div>
    )
    }
}

export default About;

这是显示 Google 地图和标记的类:

import React, { Component } from 'react';

class GoogleMap extends Component {
  constructor(props) {
    super(props);
    this.googleMapRef = React.createRef(); // Create a referance for Google Map to draw to
    console.log('Constructore')
  }

  componentDidMount(){
    console.log('componentDidMount')
    /* Create the Map */
    let googleMap = new window.google.maps.Map(this.googleMapRef.current, {
      zoom: 15,
      center: {
        lat: 51.436411,
        lng: -2.861980,
      },
      disableDefaultUI: true,
    })

    this.placeMMarkers(googleMap) // Place the markers
    this.addMapListner(googleMap) // Define a click listener to place new markers
  }

  /* Place the markers */
  placeMMarkers = (googleMap) => {
    this.props.markers.forEach((m) => {
      m.map = googleMap;
       let marker= new window.google.maps.Marker(m)
       marker.addListener('click', () => { this.props.clickedMarker(m.label); });
     }
   );
 }

 /* Map listeners */
  addMapListner = (googleMap) => {
    googleMap.addListener('click', (e) => {
      this.props.addMarker(e.latLng)
    })
  }

  render() {
    console.log('render: ' + this.props.markers) // This is showing the added markers
    return (
      <div
        id="google-map"
        ref={this.googleMapRef}
        style={{ width: '800px', height: '400px', float: 'left' }}>
      </div>
    )
  }
}

export default GoogleMap

我已经为每个函数添加了控制台日志记录,以便我可以跟踪正在发生的事情。

这里是MapMarkerDetails,当单击标记时会显示一条简单的消息。这一切都很好。

import React, { Component } from 'react';

class MapMarkerDetails extends Component {

    render(){
        return (
            <div style={{width: '100px', height: '400px', backgroundColor: 'gray', float: 'left'}}>
                {this.props.details}
            </div>
        )
    }
}

export default MapMarkerDetails

问题描述

当用户点击地图(不是标记)时,这会调用函数addMarker,该函数是从父类About 向下传递的(下面的sn-p)。在AboutaddMarker 函数中,传入了lat/lng。这表示用户单击的位置。这将转换为marker 数据对象,然后创建一个包含默认标记和新标记的新数组。我不确定我的新数组创建是否以最佳方式完成 - 如果不告诉我。

创建新数组后,我们使用this.setState({markers}) 更新组件状态。我认为这会导致重新render() 并使用添加的标记重新绘制地图。但不是。

addMarker = (latlng) => {
    let newMarker = [{
        position: { lat: latlng.lat(), lng: latlng.lng() },
        label: 'New',
        map: null,
    }];

    /* Creates a new array for updating state. Is this the best way to do this */
    let markers = [...this.state.markers, ...newMarker] 
    this.setState({markers});

    console.log(this.state) // This shows the added marker
}

发生了一些事情,导致GoogleMaprender() 函数被调用,但只显示了原始标记。数据被传递到GoogleMap 组件,因为我可以看到console.log('render: ' + this.props.markers) 的输出。但是如何让所有标记加载?

请告知About 将数据传递给GoogleMap 以便添加新标记的最佳方法。

【问题讨论】:

    标签: javascript reactjs google-maps


    【解决方案1】:

    就像您在第一次加载地图时使用componentDidMount 强制添加标记一样,您应该在道具更改时使用componentDidUpdate 执行相同的操作。在您的 GoogleMap 组件中:

    componentDidUpdate() {
      this.placeMMarkers()
    }
    

    我不会将googleMap 作为参数传递,而是将其设置为componentDidMount 中的实例变量:

    this.googleMap = new window.google.maps.Map(...
    

    然后将 placeMMarkers 更改为使用this.googleMap:

    placeMMarkers = () => {
      this.props.markers.forEach((m) => {
        m.map = this.googleMap;
        // ...
    

    由于您在placeMMarkers 中附加了一个事件处理程序,您还应该添加一些逻辑来区分新标记和现有标记,以避免向现有标记添加多个事件处理程序。

    在回答您关于如何最好地设置状态的问题时,我认为您所拥有的很好,但您不需要将新标记放在数组中:

    let newMarker = {
        position: { lat: latlng.lat(), lng: latlng.lng() },
        label: 'New',
        map: null,
    };
    let markers = [...this.state.markers, newMarker]
    

    【讨论】:

    • 谢谢汤姆费内克。你已经为自己赢得了一颗金星——或者至少是一个赞成票和一个勾号。
    猜你喜欢
    • 2014-06-15
    • 2014-10-08
    • 2014-05-17
    • 1970-01-01
    • 2013-04-20
    相关资源
    最近更新 更多