reactjsgoogle-mapsreact-google-mapsreact-google-maps-api

Google map api in my react app doesn't work


I'm going to use @react-google-maps/api@2.19.2 and I got the following error and I have no idea how to fix it. Please help me.

My code :

import React, { useState, useEffect } from "react";
import { GoogleMap, LoadScript, Marker } from "@react-google-maps/api";

const MapContainer = () => {
  const [selectedAddress, setSelectedAddress] = useState(null);

  const handleMapClick = (event) => {
    // Get the latitude and longitude of the clicked position
    const clickedLat = event.latLng.lat();
    const clickedLng = event.latLng.lng();

    // Call the Geocoding API to retrieve the address details
    const geocoder = new window.google.maps.Geocoder();
    geocoder.geocode(
      { location: { lat: clickedLat, lng: clickedLng } },
      (results, status) => {
        if (status === "OK") {
          if (results[0]) {
            // Extract the formatted address from the API response
            const address = results[0].formatted_address;

            // Update the selected address state
            setSelectedAddress(address);
          } else {
            console.log("No results found");
          }
        } else {
          console.log("Geocoder failed due to: " + status);
        }
      }
    );
  };

  const [mapLoaded, setMapLoaded] = useState(false);

  useEffect(() => {
    const script = document.createElement("script");
    script.src = `https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&libraries=places`;
    script.async = true;
    script.defer = true;
    script.onload = () => setMapLoaded(true);
    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script);
    };
  }, []);

  return (
    <div style={{ width: "100%", height: "400px" }}>
      {mapLoaded && (
        <LoadScript googleMapsApiKey="MY_API_KEY">
          <GoogleMap
            mapContainerStyle={{ width: "100%", height: "100%" }}
            center={{ lat: 53.23, lng: 35.34 }}
            zoom={10}
            onClick={handleMapClick}
          >
            {selectedAddress && <Marker position={selectedAddress} />}
          </GoogleMap>
        </LoadScript>
      )}
    </div>
  );
};

export default MapContainer;

My error:

Uncaught (in promise) TypeError: h is undefined
    fda https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places:231
    promise callback*fda/< https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places:231
    setTimeout handler*fda https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places:231
    Load https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places:14
    <anonymous> https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places:388
    <anonymous> https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places:388

I want to use the map so that the user can enter his address, but the map does not load. I used the @react-google-maps/api package, but I encountered an error.


Solution

  • You have set a condition that cannot be met initially that blocks the <LoadScript> component

    This prevents your map from rendering all together but first of all let's address the multiple issues within your code.

    First is that you are loading the Maps Javascript script manually in your useEffect hook in here:

    useEffect(() => {
      const script = document.createElement("script");
      script.src = `https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&libraries=places`;
      script.async = true;
      script.defer = true;
      script.onload = () => setMapLoaded(true);
      document.body.appendChild(script);
    
      return () => {
        document.body.removeChild(script);
      };
    }, []);
    

    This would not enable your map to load because the react-google-maps/api library is not designed this way. So I suggest you read the documentation more before trying out something for recommended ways of working on libraries. https://www.npmjs.com/package/@react-google-maps/api

    And then you are also using the built in LoadScript component from the react-google-maps/api library.

    {mapLoaded && (
      <LoadScript googleMapsApiKey="MY_API_KEY">
        <GoogleMap
          mapContainerStyle={{ width: "100%", height: "100%" }}
          center={{ lat: 53.23, lng: 35.34 }}
          zoom={10}
          onClick={handleMapClick}
        >
          {selectedAddress && <Marker position={selectedAddress} />}
        </GoogleMap>
      </LoadScript>
    )}
    

    As you can see in the above code, you have included a mapLoaded in the condition and after playing around with your code, this seems to be the one causing the issue because it prevents the <LoadScript> component from rendering all together.

    I tried moving it after the LoadScript component and the map worked, but is showing that the Maps JS script has been loaded multiple times, so what I did is I just removed the useEffect hook that tries to load the script altogether and removed the mapLoaded condition and everything seems to be working fine.

    So your code should look something like this:

    import React, { useState, useEffect } from "react";
    import { GoogleMap, LoadScript, Marker } from "@react-google-maps/api";
    
    const MapContainer = () => {
      const [selectedAddress, setSelectedAddress] = useState(null);
    
      const handleMapClick = (event) => {
        // Get the latitude and longitude of the clicked position
        const clickedLat = event.latLng.lat();
        const clickedLng = event.latLng.lng();
    
        // Call the Geocoding API to retrieve the address details
        const geocoder = new window.google.maps.Geocoder();
        geocoder.geocode(
          { location: { lat: clickedLat, lng: clickedLng } },
          (results, status) => {
            if (status === "OK") {
              if (results[0]) {
                // Extract the formatted address from the API response
                const address = results[0].formatted_address;
    
                // Update the selected address state
                setSelectedAddress(address);
              } else {
                console.log("No results found");
              }
            } else {
              console.log("Geocoder failed due to: " + status);
            }
          }
        );
      };
    
      return (
        <div style={{ width: "100%", height: "400px" }}>
          {
            <LoadScript googleMapsApiKey="MY_API_KEY">
              <GoogleMap
                mapContainerStyle={{ width: "100%", height: "100%" }}
                center={{ lat: 53.23, lng: 35.34 }}
                zoom={10}
                onClick={handleMapClick}
              >
                {selectedAddress && <Marker position={selectedAddress} />}
              </GoogleMap>
            </LoadScript>
          }
        </div>
      );
    };
    
    export default MapContainer;
    

    If you want to check it out yourself, here's a working codesandbox: https://codesandbox.io/s/loading-a-map-t2tt6m?file=/src/Map.js

    I hope this helps!