9

For some reason when I click on a single Marker all the InfoWindow shows up. I expected one InfoWindow show up when I click on one single Marker. Can someone explain why all the InfoWindow in all the Marker shows up? So when I close it InfoWindow closes too.

Expected behavior is InfoWindow open when I click on targeted Mark.

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

    this.state = {
      isOpen: false,
    };
  }

  handleToggleOpen = () => {
    this.setState({
      isOpen: true,
    });
  };

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

  render() {
    const venues = this.props.venues;

    let markers;
    let userMarkers = (
      <Marker
        position={{
          lat: Number(latCurrentLocation),
          lng: Number(lngCurrentLocation),
        }}
      />
    );
    if (venues !== null) {
      markers = venues.map((location, i) => {
        const lat = location.venue.location.lat;
        const lng = location.venue.location.lng;
        const index = i + 1;
        return (
          <Marker
            key={i}
            position={{ lat: lat, lng: lng }}
            label={index.toString()}
            onClick={() => this.handleToggleOpen()}
          >
            {this.state.isOpen && (
              <InfoWindow onCloseClick={() => this.handleToggleClose()}>
                <span>Something</span>
              </InfoWindow>
            )}
          </Marker>
        );
      });
    }

    const MapWithAMarker = withGoogleMap(props => (
      <GoogleMap
        defaultZoom={this.state.zoom}
        defaultCenter={{
          lat: Number(latCurrentLocation) || 40.7128,
          lng: Number(lngCurrentLocation) || -74.006,
        }}
      >
        {markers}
        {userMarkers}
      </GoogleMap>
    ));

    const googleMap = (
      <MapWithAMarker
        containerElement={
          <div style={{ height: this.props.containerElement }} />
        }
        mapElement={<div style={{ height: this.props.mapElement }} />}
      />
    );

    return <div>{googleMap}</div>;
  }
}

enter image description here enter image description here

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Pak Chu
  • 253
  • 1
  • 5
  • 13

3 Answers3

8

What you need is a separate isOpen state for each info window, otherwise all of them will open if isOpen is true.

Option 1: You can make a component <MarkerWithInfoWindow>, inside which you can maintain it's own isOpen state. This will still allow multiple of them open at once tho, by clicking one by one.

Option 2: If you want to keep the structure same (so you can close one if another opens), you can store an openInfoWindowMarkerId in state, something like this

this.state = {
        openInfoWindowMarkerId: ''
    }

then you can do something like

handleToggleOpen = (markerId) => {
    this.setState({
        openInfoWindowMarkerId: markerId
    });
}

and you can call it like this

<Marker
    key={i}
    position={{ lat: lat, lng: lng}}
    label={index.toString()}
    onClick={() => this.handleToggleOpen(i)} // marker ID is the key here. 
>
Palash Karia
  • 670
  • 4
  • 10
  • Hey Palash, Thanks for getting back to me. I am trying your suggestion option one. I am still confused how does it know which element to show when the Marker is clicked. Also, the Mark controls if the InfoWindow State is true or false. If I were to maintain the state in InfoWindow component doesn't that conflict with the click handler in Marker. – Pak Chu Jan 20 '18 at 17:49
  • fixed the issue. THANKS FOR GIVING ME INSIGHT! – Pak Chu Jan 20 '18 at 19:08
1

I fixed the issue as explained above.

I extracted each Mark into a component itself.

I merged Mark and InfoWindow into a single component.

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


class InfoWindowMap extends Component {

    constructor(props){
        super(props);

        this.state = {
            isOpen: false
        }

    }

    handleToggleOpen = () => {

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

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


  render() {

    return (
            <Marker
                key={this.props.index}
                position={{ lat: this.props.lat, lng: this.props.lng}}
                label={this.props.index.toString()}
                onClick={() => this.handleToggleOpen()}
            >

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


            </Marker>

        )
  }
}

export default InfoWindowMap;
jpgbarbosa
  • 780
  • 4
  • 14
Pak Chu
  • 253
  • 1
  • 5
  • 13
1
try this: 

{props.nhatro.map((nhatro, index) =>
        <Marker
          key={index}
          options={{icon: 'https://i.imgur.com/9G5JOp8.png'}}
          position={nhatro}
          onClick={()=>{ props.showInfo(index)} }
        >
          { (props.showInfoIndex == index ) && 
          <InfoWindow  onCloseClick={props.onToggleOpen}>
            <div>
              <div>nhà trọ cho thuê</div>
              <div >1.500.000đ</div>
            </div>
          </InfoWindow>}
        </Marker>
    )}

and then :

showInfo(a){
 setState({showInfoIndex: a })
}
Nguyễn Phúc
  • 273
  • 3
  • 9