skip to Main Content

I am having the issue when I try and use the Places API for address autocomplete in React with ts. When I run the project again the address autocomplete does fill out the address forms correctly but when I actually stay on that page and pick new address after new address and then refresh I start getting TypeErrors like the one mentioned in the title as well as this error You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors.

Following code resulting in the error:

  const [isGoogleMapsLoaded, setGoogleMapsLoaded] = useState(false);

  useEffect(() => {
    if (
      document.querySelector(
        'script[src*="https://maps.googleapis.com/maps/api/js"]'
      )
    ) {
      return;
    }

    const script = document.createElement("script");
    script.src = `https://maps.googleapis.com/maps/api/js?key=${
      import.meta.env.VITE_GOOGLE_MAP_IMBED_API_KEY
    }&libraries=places&callback=initMap`;
    script.async = true;
    window.initMap = () => setGoogleMapsLoaded(true);
    document.body.appendChild(script);
  }, []);

  const autocompleteInputRef = useRef(null);

  useEffect(() => {
    (async () => {
      if (!isGoogleMapsLoaded) return;

      try {
        const googleMaps = await loadGoogleMapsApi({
          key: import.meta.env.VITE_GOOGLE_MAP_IMBED_API_KEY,
          libraries: ["places"],
        });

        if (
          !window.google ||
          !window.google.maps ||
          !window.google.maps.places
        ) {
          return;
        }

        if (!autocompleteInputRef.current) return;

        const autocomplete = new googleMaps.places.Autocomplete(
          autocompleteInputRef.current,
          {
            types: ["address"],
            componentRestrictions: { country: "us" },
          }
        );
        console.log(autocomplete);

        autocomplete.addListener("place_changed", () => {
          const place = autocomplete.getPlace();
          if (!place || !place.address_components) return;

          const streetAddress1Component = place.address_components.find(
            (component) => component.types.includes("street_number")
          );
          const streetAddress2Component = place.address_components.find(
            (component) => component.types.includes("route")
          );
          const cityComponent = place.address_components.find((component) =>
            component.types.includes("locality")
          );
          const stateComponent = place.address_components.find((component) =>
            component.types.includes("administrative_area_level_1")
          );
          const zipCodeComponent = place.address_components.find((component) =>
            component.types.includes("postal_code")
          );

          if (
            !streetAddress1Component ||
            !streetAddress2Component ||
            !cityComponent ||
            !stateComponent ||
            !zipCodeComponent
          ) {
            // Fallback mechanism to parse the full address
            const fullAddress = place.formatted_address
              ? place.formatted_address.split(", ")
              : [];
            setFormData({
              ...formData,
              streetAddress1: fullAddress[0] || "",
              city: fullAddress[1] || "",
              state: fullAddress[2]?.split(" ")[0] || "",
              zipCode: fullAddress[2]?.split(" ")[1] || "",
            });
          } else {
            const streetAddress1 = streetAddress1Component.long_name;
            const streetAddress2 = streetAddress2Component.long_name;
            const city = cityComponent.long_name;
            const state = stateComponent.short_name;
            const zipCode = zipCodeComponent.long_name;

            setFormData({
              ...formData,
              streetAddress1: `${streetAddress1} ${streetAddress2}`,
              city,
              state,
              zipCode,
            });
          }
        });
      } catch (error) {
        console.error(error);
      }
    })();
  }, [isGoogleMapsLoaded]);

Like I said with the current code I have there it does work properly sometimes but other times it starts giving me the TypeError and then just stops working completely.

2

Answers


  1. Chosen as BEST ANSWER

    I ended up going with a different library completely when finding a solution to this. As you can see in the updated code I used Loader which worked better in my use case.


  2. Loading Google Maps Api several times in your react app leads to this error…

    Please make sure you follow the documentation and best practices properly
    https://developers.google.com/maps/documentation/javascript/overview

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search