Google Maps API、Marker onClick 侦听器未按预期工作

问题描述

现在我正在尝试构建一张地图,显示印度尼西亚的所有医院(以及后来的关于新冠肺炎病例),到目前为止,我已经能够成功地从 json 文件获取位置并将其映射到地图上.我的地图有一个按钮,如果你点击它,印度尼西亚的所有医院都会在地图上显示标记。我现在想要做的是在用户单击特定标记时弹出医院名称的 InfoWindow。

我是如何尝试接近它的: 为所有医院标记创建一个状态布尔数组,以查看医院是否已被点击 如果点击了医院,则输出一个带有医院名称的信息窗口。

问题: 似乎当我单击按钮以显示印度尼西亚的所有医院时,它将状态布尔数组更新为全部为真。我不知道为什么会这样,当我点击一个特定的标记时,状态数组没有改变。

如果您需要完整代码,这是我的 git 存储库:https://github.com/ktanojo17505/google-map-react

这是我的状态:

state = { 
    address: "",city: "",area: "",state: "",zoom: 11,height: 400,mapPosition: {
      lat: 0,lng: 0
    },markerPosition: {
      lat: 0,placeHospitals: false,Hospitals: [],didClickHospital: []
  };

这是我的构造函数

constructor(props) {
    super(props);
    var HospitalLocations = [];
    var clickHospital = [];
    var position;
    var hospitalName;
    var id;
    for (let index = 0; index < HospitalData.hospitals.length; ++index) {
      id = index;
      var latitude = HospitalData.hospitals[index].latitude;
      var longitude = HospitalData.hospitals[index].longitude;
      position = { latitude,longitude };
      hospitalName = HospitalData.hospitals[index].nama;
      var entry = { id,position,hospitalName };
      HospitalLocations.push(entry);
      clickHospital.push(false);
    }
    this.state.Hospitals = HospitalLocations;
    this.state.didClickHospital = clickHospital;
  }

这是我的回报

return (
      <div style={{ padding: "1rem",margin: "0 auto",maxWidth: 1000 }}>
        <h1>Google Maps Basic</h1>
        <Descriptions bordered>
          <Descriptions.Item label="City">{this.state.city}</Descriptions.Item>
          <Descriptions.Item label="Area">{this.state.area}</Descriptions.Item>
          <Descriptions.Item label="State">
            {this.state.state}
          </Descriptions.Item>
          <Descriptions.Item label="Address">
            {this.state.address}
          </Descriptions.Item>
        </Descriptions>
        <MapWithAMarker
          googleMapURL={
            "https://maps.googleapis.com/maps/api/js?key=" +
            config.GOOGLE_API_KEY +
            "&v=3.exp&libraries=geometry,drawing,places"
          }
          loadingElement={<div style={{ height: `100%` }} />}
          containerElement={<div style={{ height: `400px` }} />}
          mapElement={<div style={{ height: `100%` }} />}
        />
        <div style={{ marginTop: "2.5rem" }}>
          <Button onClick={this.placeHospitals}>Hospitals</Button>
        </div>
      </div>
    );

MapwithMarker

const MapWithAMarker = withScriptjs(
      withGoogleMap(props => (
        <div>
          <GoogleMap
            defaultZoom={this.state.zoom}
            defaultCenter={{
              lat: this.state.mapPosition.lat,lng: this.state.mapPosition.lng
            }}
            options={options}
            onClick={this.placeMarker}
          >
            <Marker
              draggable={true}
              onDragEnd={this.onMarkerDragEnd}
              position={{
                lat: this.state.markerPosition.lat,lng: this.state.markerPosition.lng
              }}
            >
              <InfoWindow>
                <div>{this.state.address}</div>
              </InfoWindow>
            </Marker>
            {this.state.placeHospitals &&
              this.state.Hospitals.map(hospitalLoc => ( // Place the locations if Hospitals Button is clicked 
                <Marker
                  draggable={false}
                  position={{
                    lat: hospitalLoc.position.latitude,lng: hospitalLoc.position.longitude
                  }}
                  key={hospitalLoc.id}
                  onClick={this.clickHospital(hospitalLoc.id)} // Change the state of the Hospital InfoWindow 
                >
                  {/* {this.state.didClickHospital[index] && ( // If true output an infowindow of the hospital name 
                    <InfoWindow>
                      <div>{hospitalLoc.name}</div>
                    </InfoWindow>
                  )} */}
                </Marker>
              ))}
            <AutoComplete
              style={{
                width: "100%",height: "40px",paddingLeft: 16,marginTop: 2,marginBottom: "2rem"
              }}
              types={["(regions)"]}
              onPlaceSelected={this.onPlaceSelected}
            />
          </GoogleMap>
        </div>
      ))
    );

点击医院

clickHospital = id => {
    console.log("clicked");
    // var tempClickHospital = this.state.didClickHospital;
    // console.log(tempClickHospital[index]);
    // tempClickHospital[index] = !tempClickHospital[index];
    // console.log(tempClickHospital[index]);
    // this.setState({ didClickHospital: tempClickHospital });
    // console.log(this.state.didClickHospital);
  };

这是我的代码输出(点击医院之前)1

这是我的代码输出(点击医院后)2

如果有人能指出我做错了什么,那将很有帮助,谢谢!

解决方法

您可以直接映射 json 文件中的每个数据,以创建一个单独的 <Marker>,其中包含 <InfoWindow>

这里有一个 working sample code 和下面关于如何执行此操作的代码片段:

import React,{ Component } from "react";
import {
  withGoogleMap,GoogleMap,Marker,InfoWindow
} from "react-google-maps";
//import the json data of your hospital info
import data from "./data.json";
import "./style.css";

class Map extends Component {
  constructor(props) {
    super(props);

    this.state = {
      hospitalId: "",addMarkerBtn: false
    };
  }
  addMarkerFunction = () => {
    this.setState({
      addMarkerBtn: true
    });
  };

  handleToggleOpen = id => {
    this.setState({
      hospitalId: id
    });
  };

  render() {
    const GoogleMapExample = withGoogleMap(props => (
      <GoogleMap
        defaultCenter={{ lat: -6.208763,lng: 106.845599 }}
        defaultZoom={16}
      >
        {this.state.addMarkerBtn === true &&
          data.map(hospital => (
            <Marker
              key={hospital.id}
              position={{ lat: hospital.lat,lng: hospital.lng }}
              onClick={() => this.handleToggleOpen(hospital.id)}
            >
              {this.state.hospitalId === hospital.id && (
                <InfoWindow
                  onCloseClick={this.props.handleCloseCall}
                  options={{ maxWidth: 100 }}
                >
                  <span>{hospital.id}</span>
                </InfoWindow>
              )}
            </Marker>
          ))}
      </GoogleMap>
    ));

    return (
      <div>
        <button id="addMarker" onClick={() => this.addMarkerFunction()}>
          Add Marker
        </button>
        <GoogleMapExample
          containerElement={<div style={{ height: `500px`,width: "500px" }} />}
          mapElement={<div style={{ height: `100%` }} />}
        />
      </div>
    );
  }
}

export default Map;