Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
spaceforestchu opened this issue Jan 19, 2018 · 20 comments

Comments

@spaceforestchu
Copy link

spaceforestchu commented Jan 19, 2018

Hi all,

I am having an issue with making the InfoWindow shows up for the Mark I click on.
The expect behavior is when I click on the mark it will only shows information about that mark in the InfoWindow.

However, What I am getting now is that when I click on a marker all the marker shows up. And when I tried to close it rerender the app.

Any Idea how to fix this?

  class VenuesMap extends Component {

constructor(props){
	super(props);

	this.state = {
		zoom: 11,
		isOpen: false
	}

handleToggle = () => {
	this.setState({
		isOpen: !false
	});
}
  render() {

		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.handleToggle}
				>
				{this.state.isOpen &&
				<InfoWindow
						onCloseClick={this.handleToggle}
						>
					<span>Something</span>
				</InfoWindow>
			 }
			</Marker>
			)
		})

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

           >
	{markers}
	{userMarkers}
      </GoogleMap>
   );

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

        return (
		<div>
			{googleMap}
		</div>
	)
      }
   }

 export default connect(stateToProps)(VenuesMap)

screen shot 2018-01-18 at 11 53 01 pm
screen shot 2018-01-18 at 11 53 14 pm

@spaceforestchu spaceforestchu changed the title InfoWindow already open right away even I have disableAutoPan to true React Google Map InfoWindow showing all the info when I click on a single Mark Jan 19, 2018
@spaceforestchu
Copy link
Author

I fixed. I replaced with Marker and InfoWindow to its 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}>
			 <h1>{this.props.location.venue.name}</h1>
		 </InfoWindow>
	 	}


		</Marker>

	)

}
}

export default InfoWindowMap;

@hrashid
Copy link

hrashid commented Jan 25, 2018

Hi @spaceforestchu - is this the complete code for the fix? I tried to replicate your fix but couldn't seem to do it. Is there a separate component for GoogleMap? If so, can you post your entire fix?

Thanks for posting the solution!

@spaceforestchu
Copy link
Author

@hrashid sorry I just saw this.
I made an info window component.
<Marker key={this.props.index} position={{
lat: this.props.lat,
lng: this.props.lng
}} label={this.props.index.toString()}
onClick={() => this.handleClicks(this.props.venueID)}
>

        {
          this.state.isOpen &&

					<InfoWindow onCloseClick={() => this.setState({isOpen: false})}>
              <div>
                <h4>{this.props.location.venue.name}</h4>
                <img src={`${venuePhoto}`}/>
                <span>{number}</span>
              </div>
            </InfoWindow>

        }

      </Marker>

then I put the infoWindowMap component in sindei google map component.

	<InfoWindowMap
						key={index}
						lat={lat}
						lng={lng}
						index={index}
						location={location}
						indexValue={index}
						venueID={venueID}
						
						/>

You can find the code in my github the project is called your 4 square. Let me know if you need any help.

@joont92
Copy link

joont92 commented Feb 26, 2018

I have same problem and I solved like following..

class GoogleMapBox extends React.Component{
	state = {
		position : null
	}

	handleToggleOpen(item){
		this.setState({
			position : {
				lat : item.lat,
				lng : item.lng
			}			
		})
	}

	render(){
		return (
			<GoogleMap ....>
				{markers.map((item) => (
					<Marker
					    key={this.props.index}
					    position={{ lat: this.props.lat, lng: this.props.lng}}
					    label={this.props.index.toString()}
					    onClick={() => this.handleToggleOpen(item)}
					/>
				)}
				

				{this.state.position && 
					 <InfoWindow position={this.state.position}>
					     <h1>{this.props.location.venue.name}</h1>
					 </InfoWindow>
				 }
			</GoogleMap>
		)
	}	
}

(this code is not exact. cause I quickly typed it in this editor)
this way is isn't in .

It works good. I recommend this way.

@nguyenvanphuc2203
Copy link

nguyenvanphuc2203 commented Mar 13, 2018

my solution below
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 })
}

@tetar998
Copy link

@nguyenvanphuc2203 where did you put your ShowInfo ?

@nguyenvanphuc2203
Copy link

image

@pttse
Copy link

pttse commented Jul 5, 2018

@nguyenvanphuc2203 Thanks for your code. However, after opening an info window and closing it once. The info window will not be able to show up again.

So below is the quick fix, I just added an additional condition for showing the info window (ie . props.isOpen).

      {locationMarkers && locationMarkers.map((marker) =>
        <Marker key={marker.index} position={marker.position} onClick={() => { props.showInfo(marker.index) }}>
          {(props.isOpen && props.showInfoIndex == marker.index) &&
            <InfoWindow onCloseClick={props.onToggleOpen}>
              <div>
                {marker.info}
              </div>
            </InfoWindow>}
        </Marker>
      )}

If there is another better fix, please let me know!

@nguyenvanphuc2203
Copy link

nice man :D

@dnagy14
Copy link

dnagy14 commented Jul 26, 2018

@nguyenvanphuc2203 @pttse
IMO, the easiest and the right way is to 'reset' showInfo prop on close.
BTW, you could use only one function that handles opening and closing InfoWindow.
My code looks like this:

withStateHandlers(() => ({
  isOpen: false,
  infoIndex: null
}), {
  showInfo: ({ isOpen, infoIndex }) => (index) => ({
    isOpen: infoIndex !== index || !isOpen,
    infoIndex: index
  })
})
<Marker onClick={() => props.showInfo(marker.index)}>
  {(props.isOpen && props.infoIndex === marker.index) &&
    <InfoWindow onCloseClick={props.showInfo}>
      <span>{marker.info}</span>
    </InfoWindow>}
</Marker>

@jaure96
Copy link

jaure96 commented Dec 13, 2018

**Hi guys!
Can someone help me?

I have this error: **
image

in the following peace of code:

import React from 'react'
import PropTypes from 'prop-types'

import template from 'modules/template'
import OverlayView from './CustomOverlayView'

import IconButton from '@material-ui/core/IconButton';
import Place from '@material-ui/icons/Place'

import blueGrey from '@material-ui/core/colors/blueGrey';
import red from '@material-ui/core/colors/red';

import { getColors } from 'utils/status'

import PersonalizedInfoWindow from './PersonalizedInfoWindow'

const disabledColor = blueGrey[500]

const DefaultIcon = ({
status,
isEnabled = true,
isSelected = false,
...other
}) => {
const { primary = red[500] } = getColors(status)
let color = (!isEnabled && !isSelected) ? disabledColor : primary
const iconStyle = { color }
return <Place fontSize="large" style={iconStyle} {...other} />
}

class CustomOverlayMarker extends React.Component {

constructor(props) {
super(props)

this.state = {
  isOpen: false
}

}

handleMouseOver = () => {
this.setState({
isOpen: true
})
}

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

render() {

let markerIcon
if (this.props.children) {
  markerIcon = React.cloneElement(this.props.children, this.props.size)
} else {
  markerIcon = <DefaultIcon {...this.props} />
}

let infoWindow = null
if (this.state.isOpen) {
  infoWindow = <PersonalizedInfoWindow position={this.props.position} label={this.props.label} />
}

// For some reason the general provider is not inherited in the OverlayView :-S
const MuiThemeProvider = template.components.ThemeProvider

return (
  <OverlayView
    mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
    position={this.props.position}
    getPixelPositionOffset={() => ({ x: -this.props.size / 2, y: -this.props.size })}
  >
    <MuiThemeProvider>
      <IconButton
        tooltip={this.props.label}
        onClick={this.props.onClick}
        onMouseOver={this.handleMouseOver()}
        onMouseOut={this.handleMouseOver()}
      >
        {markerIcon}
        {infoWindow}
      </IconButton>

    </MuiThemeProvider>

  </OverlayView>
)

}

}

CustomOverlayMarker.propTypes = {
size: PropTypes.number,
label: PropTypes.string,
position: PropTypes.object,
isEnabled: PropTypes.bool,
isSelected: PropTypes.bool,
onClick: PropTypes.func
}

export default CustomOverlayMarker

Does someone know how to avoid this??

@JustFly1984
Copy link

handleMouseOver = () => {
if (!this.state.isOpen) {
this.setState({
isOpen: true
})
}
}

handleMouseOver = () => {
if (this.state.isOpen) {
this.setState({
isOpen: false
})
}
}

@jaure96
Copy link

jaure96 commented Dec 13, 2018

The solution was as simple as adding this:

this.handleMouseOver()} onMouseOut={()=>this.handleMouseOver()} >

@vinhp1292
Copy link

vinhp1292 commented Jan 7, 2019

My solution:

withStateHandlers(() => ({
    isOpen: false,
    markerIndex: 0
  }), {
    onToggleOpen: ({ isOpen }) => (index) => ({
      isOpen: !isOpen,
      markerIndex: index
    })
  })


<Marker
onClick={ ()=> {props.onToggleOpen(index} }>
{ props.isOpen && props.markerIndex === index &&
              <InfoWindow onCloseClick={props.onToggleOpen}>
                <div>Working</div>
              </InfoWindow>
}
</Marker>

@senelithperera
Copy link

senelithperera commented Oct 15, 2019

The infoWindow corresponding to the marker doesn't get shown up when i click on the marker. The markers keep refreshing when i click on them. I can't figure out what i've done wrong. Can anybody help me with this ?

import { GoogleApiWrapper, Map, Marker, InfoWindow } from "google-maps-react";
import React, { useState } from "react";
import { GOOGLE_API_KEY } from "../../../../../utils/environment";
import styles from "./../../../wrappers/widgetsWrapper.module.scss";

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

const GoogleMaps = props => {
  const [infoOpen, setInfoOpen] = useState(null);

  const { chartData } = props;

  const handleToggle = (id) => {
    setInfoOpen(id)
  }

  const formatData = (chartData) => {
    chartData.map((place, index) => {
      place.id = "id" + index
    })
    const data = chartData
    return data
  }
  // const mapDetails = formatData(chartData.data.mapData)
  // console.log("mapDetails : ", mapDetails);
  const mapDetails = [
    {
      "label": "Lady Gray Gourmet Medibles",
      "lat": 61.217835,
      "lng": -149.88037
    },
    {
      "label": "Lady Gray Gourmet Medibles",
      "lat": 64.837205,
      "lng": -147.806626
    },
    {
      "label": "Glacier Extracts",
      "lat": 64.837205,
      "lng": -147.806626
    },
    {
      "label": "Baked Alaska",
      "lat": 61.191401,
      "lng": -149.912576
    },
  ]

  return (
    <React.Fragment>
      <div className={styles.dashboardWidgetCard}>
        <Map
          google={props.google}
          zoom={4}
          style={mapStyles}
          initialCenter={{ lat: 61.217835, lng: -149.88037 }}
        >
          {mapDetails.map((mapData, index) => (
            <Marker
              key={index}
              position={{ lat: mapData.lat, lng: mapData.lng }}
              onClick={() => { handleToggle(index) }}
            >
              {(infoOpen == index) &&
                <InfoWindow>
                  <h3>helooo</h3
                </InfoWindow>
              }

            </Marker>
          ))}
        </Map>
      </div>
    </React.Fragment>
  );
};

export default GoogleApiWrapper({
  apiKey: GOOGLE_API_KEY
})(GoogleMaps);

@JustFly1984
Copy link

@senelithperera
The repo of this project is unmaintained more than a year, and we had build new version https://www.npmjs.com/package/@react-google-maps/api

We had rewrite it to TypeScript, and updating it frequently: https://github.com/JustFly1984/react-google-maps-api/tree/master/packages/react-google-maps-api
You can enjoy autocomplete.

You can see our docs: https://react-google-maps-api-docs.netlify.com/

Also a lot of examples: https://react-google-maps-api-gatsby-demo.netlify.com/ https://github.com/JustFly1984/react-google-maps-api/tree/master/packages/react-google-maps-api-gatsby-example/src/examples

The bundle size is much smaller: https://bundlephobia.com/result?p=@react-google-maps/api@1.7.5

Enjoy!

@senelithperera
Copy link

@JustFly1984 Just after posting this question, I found your github repo. The issue was fixed.

@mahendragurav2
Copy link

@nguyenvanphuc2203 Thanks for your code. However, after opening an info window and closing it once. The info window will not be able to show up again.

So below is the quick fix, I just added an additional condition for showing the info window (ie . props.isOpen).

      {locationMarkers && locationMarkers.map((marker) =>
        <Marker key={marker.index} position={marker.position} onClick={() => { props.showInfo(marker.index) }}>
          {(props.isOpen && props.showInfoIndex == marker.index) &&
            <InfoWindow onCloseClick={props.onToggleOpen}>
              <div>
                {marker.info}
              </div>
            </InfoWindow>}
        </Marker>
      )}

If there is another better fix, please let me know!

Could you please share the all the code. I am trying with this but getting some issues

@JustFly1984
Copy link

@farrukh-malik
Copy link

Here is a complete solution InfoWindow shows. i have also attached the link you can see for more understanding.. https://codesandbox.io/s/quizzical-hermann-5ehs7

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

export class MapContainer extends Component {
  state = {
    activeMarker: {},
    selectedPlace: {},
    showingInfoWindow: false
  };

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

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

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

  render() {
    if (!this.props.loaded) return <div>Loading...</div>;

    return (
      <Map
        className="map"
        google={this.props.google}
        onClick={this.onMapClicked}
        style={{ height: "100%", position: "relative", width: "100%" }}
        zoom={13}
      >
        <Marker
          name="Marker 1"
          onClick={this.onMarkerClick}
          position={{ lat: 37.778519, lng: -122.40564 }}
        />

        <Marker
          name="Marker 2"
          onClick={this.onMarkerClick}
          position={{ lat: 37.759703, lng: -122.428093 }}
        />

        <Marker name="Marker 3" onClick={this.onMarkerClick} />

        <InfoWindow
          marker={this.state.activeMarker}
          onClose={this.onInfoWindowClose}
          visible={this.state.showingInfoWindow}
        >
          <div>
            <h4>{this.state.selectedPlace.name}</h4>
          </div>
        </InfoWindow>
      </Map>
    );
  }
}
export default GoogleApiWrapper({
  apiKey: "",
  version: "3.38"
})(MapContainer);

enter image description here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests