简体   繁体   中英

I want to show info window when I click on google map marker in ReactJS App?

I used infoWindow but when I click on marker, no infoWindow shows. How it will be shown by clicking the marker? I am getting the markers from props. Markers shown on map but these are not clickable. If I call a function on Click and show alert box, then all the data shows in the alert box. But I only want to open infoWindow on marker click.

import React, { Component } from "react";
import { Map, GoogleApiWrapper, Marker, InfoWindow } from 'google-maps-react';
import logo from '../assests/fbicon.png'

const mapStyles = {
  width: '100%',
  height: '50%'
};

class LiveLocation extends Component {
  constructor(props) {
    super(props);
    this.state = {
      lati: "",
      long: "",
      isOpen: false,
      showingInfoWindow: false,  
      activeMarker: {},         
      selectedPlace: {},       
      markerMap: "",
      selectedPlace: ""
    };
  }

  onMarkerClick = (props, marker, e) =>
    this.setState({
      selectedPlace: props,
      activeMarker: marker,
      showingInfoWindow: true
    });

  onClose = props => {
    if (this.state.showingInfoWindow) {
      this.setState({
        showingInfoWindow: false,
        activeMarker: null
      });
    }
  }
  handleToggleOpen = () => {

    this.setState({
      isOpen: true
    });
  }

  handleToggleClose = () => {
    this.setState({
      isOpen: false
    });
  }

  displayMarkers = () => {
    console.log(this.props.store)
    return this.props.store.map((stores, index) => {
      console.log(stores._id)
      return (
        <Marker
          key={index}
          position={{ lat: stores.lat, lng: stores.lng }}
          label={index}
          onClick={() => this.handleToggleOpen()}
          icon={{url:logo,scaledSize:new window.google.maps.Size(40,40)}}
        >

          {
            this.state.isOpen && 
            <InfoWindow  onCloseClick={this.onClose}>
              <span>Something</span>
            </InfoWindow>
          }

        </Marker>
      );
    });
  };

  componentDidMount() {
    navigator.geolocation.getCurrentPosition((position) => {
      this.setState({
        lati: position.coords.latitude,
        long: position.coords.longitude
      });
    });
  }


  render() {
    return (
      <>
        {console.log(this.props)}
        <div>
          <Map
            google={this.props.google}
            zoom={10}
            style={mapStyles}
            initialCenter={{
              lat: this.props.lati,
              lng: this.props.long

            }}
          >
            {this.displayMarkers()}
          </Map>

        </div>

      </>
    );
  }
}

There are a couple of things I noticed in the code you provided,

  1. You set your initialCenter to the this.props.lati and this.props.long however I noticed that you are getting the location of the user in the componentDidMount where you set the state of lati and long . Do you have lati and long variable in your props or do you mean to use the lati and long from the state? If so,you need to use the this.state.lati or this.state.long . The value of your state is empty and it will default the initialCenter to (0,0). If you want it to center at the user location use center parameter instead of initialCenter .

  2. In your onClick in Marker object, you need to call the {this.onMarkerClick} function and you can remove the handleToggleOpen and handleToggleClose function. You can also remove these in your state:

   isOpen: false,
   markerMap: "",
   selectedPlace: ""
  1. In your label parameter in the Marker, you are passing {index} and the datatype of this is not a string. labels need strings for it to work. You can make it {index.toString()}.

  2. To show the InfoWindow, you don't need to append it inside the object in your displayMarkers function. Put it after you call {this.displayMarkers()} in your Map object.

You can check this code and code snippet I made to achieve your use case. Note that I used sample props value and just use a props value for the center of the map. The rest, I derived from your code. To make the code work, you need to put your API key.

CODE SNIPPET

import React, { Component } from 'react';
import { Map, GoogleApiWrapper, Marker, InfoWindow } from 'google-maps-react';

const mapStyles = {
  width: '100%',
  height: '50%'
};

class LiveLocation extends Component {
  constructor(props) {
    super(props);
    this.state = {
      lati: this.props.center.lat,
      long: this.props.center.lng,
      showingInfoWindow: false,
      activeMarker: {},
      selectedPlace: {}
    };
  }

  onMarkerClick = (props, marker, e) =>
    this.setState({
      selectedPlace: props,
      activeMarker: marker,
      showingInfoWindow: true
    });

  onInfoWindowClose = () => {
    this.setState({
      activeMarker: null,
      showingInfoWindow: false
    });
  };
  



  displayMarkers = () => {
    return this.props.store.map((stores, index) => {
      return (
        <Marker
          key={index}
          position={{ lat: stores.lat, lng: stores.lng }}
          label={index.toString()}
          name={stores.id}
          onClick={this.onMarkerClick}
          //icon={{url:logo,scaledSize:new window.google.maps.Size(40,40)}}
        />
      );
    });
  };

  componentDidMount() {
    navigator.geolocation.getCurrentPosition(position => {
      this.setState({
        lati: position.coords.latitude,
        long: position.coords.longitude
      });
    });
  }

  render() {
    return (
      <>
        <div>
          <Map
            google={this.props.google}
            zoom={14}
            style={mapStyles}
            initialCenter={{
              lat: this.state.lati,
              lng: this.state.long
            }}
          >
            {this.displayMarkers()}
            <InfoWindow
              marker={this.state.activeMarker}
              onClose={this.onInfoWindowClose}
              visible={this.state.showingInfoWindow}
            >
              <div>
                <h4>{this.state.selectedPlace.name}</h4>
              </div>
            </InfoWindow>
          </Map>
        </div>
      </>
    );
  }
}

export default GoogleApiWrapper({
  apiKey: 'YOUR_KEY'
})(LiveLocation);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM