javascriptreactjsgoogle-mapsnext.js13react-google-maps-api

Two tooltips/dailog when clicking on marker @react-google-maps/api


Consider:

Enter image description here

When I click on the marker, it shows two tooltips/dialog. I am using "@react-google-maps/api": "^2.19.2" in Next.js TypeScript. I am trying to show the tooltip when I click on a marker in this package. The first tooltip is blank, and the second tooltip contains my content. I am using the following code:

import {
  GoogleMap,
  InfoWindow,
  LoadScript,
  MarkerF,
  Marker,
} from '@react-google-maps/api';

const containerStyle = {
  width: '100%',
  height: '500px',
};

const markers = [
  {
    id: 1,
    name: 'Chicago, Illinois',
    position: { lat: 41.881832, lng: -87.623177 },
  },
  {
    id: 2,
    name: 'Denver, Colorado',
    position: { lat: 39.739235, lng: -104.99025 },
  },
  {
    id: 3,
    name: 'Los Angeles, California',
    position: { lat: 34.052235, lng: -118.243683 },
  },
  {
    id: 4,
    name: 'New York, New York',
    position: { lat: 40.712776, lng: -74.005974 },
  },
];
const MapComponent: FC= () => {
  const [activeMarker, setActiveMarker] = useState<number>();
  const handleActiveMarker = (marker: number) => {
    if (marker === activeMarker) {
      return undefined;
    }
    setActiveMarker(marker);
  };
  const handleOnLoad = (map: google.maps.Map) => {
    const bounds = new google.maps.LatLngBounds();
    markers.forEach(({ position }) => bounds.extend(position));
    map.fitBounds(bounds);
  };

  return (
    <LoadScript googleMapsApiKey={process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!}>
      <GoogleMap
        onLoad={handleOnLoad}
        mapContainerStyle={containerStyle}
        zoom={10}
      >
        {markers.map(({ id, name, position }) => (
          <MarkerF
            key={id}
            position={position}
            onClick={() => handleActiveMarker(id)}
          >
            {activeMarker === id ? (
              <InfoWindow onCloseClick={() => setActiveMarker(undefined)}>
                <div key={id}>{name}</div>
              </InfoWindow>
            ) : null}
          </MarkerF>
        ))}
      </GoogleMap>
    </LoadScript>
  );
};

This code works correctly for the first tooltip, but the second tooltip is not displayed. How can I show only one tooltip when I click on this or how can I hide one?


Solution

  • Use <InfoWindowF /> component instead of the <InfoWindow /> component since you are also using the functional based <MarkerF /> component

    The react-google-maps/api library have 2 different types of components,

    1. Class Based - The components without "F" at the end. e.g. <Marker />
    2. Function Based - The components with "F" at the end. e.g. <MarkerF />

    see github repo for more information: https://github.com/JustFly1984/react-google-maps-api/tree/master/packages/react-google-maps-api

    So after playing around with your code, I found out that you were still using the class based Info Window component in a function based Marker component. This could have caused some compatibility issue. So what I did to fix this is I just properly imported the InfoWindowF,

    import {
      GoogleMap,
      InfoWindowF,
      LoadScript,
      MarkerF,
    } from "@react-google-maps/api";
    

    Then change the Info Window component you use inside the Marker component into something like this,

    {markers.map(({ id, name, position }) => (
      <MarkerF
        key={id}
        position={position}
        onClick={() => handleActiveMarker(id)}
      >
        {activeMarker === id ? (
          <InfoWindowF onCloseClick={() => setActiveMarker(undefined)}>
            <div key={id}>{name}</div>
          </InfoWindowF>
        ) : null}
      </MarkerF>
    ))}
    

    Then everything should be fine:

    Working sample screenshot

    Here's a codesandbox link if you want to see it for yourself: https://codesandbox.io/s/tooltip-duplicate-stack-overflow-fix-pmcscz

    Hope this helps!