Search code examples
javascriptreactjstypescriptnext.jsreact-google-maps

TypeScript | Next.js | Google Maps React - infoWindow.close is possibly undefined


I develop a small project in next.js (typescript), which uses the google maps api, with a KmlLayer. I would like my map to interact with my component. It works pretty well so far, when I close my SensorInfo component, my infoWindow is closed, and vice versa. To do this, I use in the onGoogleApiLoaded callback of my map a unique infoWindow, which I display manually, so that I can interact with it thanks to my other component.

My problem comes from the compiler, which tells me that the close() function of iWindow is possibly undefined.

Here is my code:

import SensorInfo from './SensorInfo';
import GoogleMapReact from 'google-map-react';
import { useState } from 'react';

export default function HomeMap() {
  const [markerData, setMarkerData] = useState(null);
  const [iWindow, setIWindow] = useState(null); // add this line to define iWindow

  const handleMarkerClick = (marker: any) => {
    setMarkerData(marker.featureData);
    console.log(marker)
  };

  const handleSensorInfoCloseAction = () => {
    setMarkerData(null);
    iWindow.close()
  }

  return (
    <>
      <div style={{ height: "700px", width: "100%" }}>
        <GoogleMapReact
          yesIWantToUseGoogleMapApiInternals={true}
          bootstrapURLKeys={{ key: `${process.env.NEXT_PUBLIC_GOOGLE_MAPS_KEY}` }}
          defaultCenter={{ lat: 41.876, lng: -87.624 }}
          defaultZoom={10}
          onGoogleApiLoaded={({ map, maps }) => {
            const newIWindow = new maps.InfoWindow();
            setIWindow(newIWindow);
            const kmlLayer = new maps.KmlLayer(
              "https://raw.githubusercontent.com/Nathaniael/test/main/test4",
              {
                preserveViewport: false,
                map: map,
                suppressInfoWindows: true
              }
            );
            maps.event.addListener(kmlLayer, 'click', function(evt: any) {
              newIWindow.setContent(evt.featureData.infoWindowHtml);
              newIWindow.setPosition(evt.latLng);
              newIWindow.open(map);
            })
            maps.event.addListener(kmlLayer, "click", handleMarkerClick);
            maps.event.addListener(newIWindow, "closeclick", function() {
              setMarkerData(null);
            } )
          }}
        >
        </GoogleMapReact>
      </div>
      { markerData &&
        <SensorInfo markerData={markerData} onClose={handleSensorInfoCloseAction}/>
      }
    </>
  );
}

I tried to give a type to the newIWindow object, but I can't find a type to associate with.

I also tried to add a null check before using iWindow.close() but I have a different error: property close does not exist on type never


Solution

  • Currently, google-map-react does not seem to have TypeScript types, hence Eslint suggests installing @types/google-map-react. But even then maps has a type of any.

    So you can only use any here, if you are not able to define types yourself, like so:

      //...
    
      const [iWindow, setIWindow] = useState<any>(null);
    
      //...
    
      const handleSensorInfoCloseAction = () => {
        setMarkerData(null);
        iWindow?.close();
      };