React Google Map InfoWindow showing all the info when I click on a single Mark

14,196

Solution 1

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. 
>

Solution 2

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;
Share:
14,196
Pak Chu
Author by

Pak Chu

Updated on June 29, 2022

Comments

  • Pak Chu
    Pak Chu almost 2 years

    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