googlemaps / js-api-loader

Load the Google Maps JavaScript API script dynamically.
Apache License 2.0
337 stars 64 forks source link

Maps: @googlemaps/js-api-loader importLibrary fails sometimes even after multiple tries. #838

Open grusingh opened 5 months ago

grusingh commented 5 months ago

I am using the @googlemaps/js-api-loader package in a React app. I am noticing that for some users the map libraries fail to load even after multiple retries.

Code:

import React, {createContext, useContext, useEffect, useState} from 'react';
import {Loader} from '@googlemaps/js-api-loader';

const GoogleMapsContext = createContext({
    googleMapsLoaded: false,
    googleMapsLibraries: null,
});

const MAX_RETRIES = 3; 

const loadLibraries = (loader, retries = MAX_RETRIES) => {
    return Promise.allSettled([
        loader.importLibrary('core'),
        loader.importLibrary('maps'),
        loader.importLibrary('marker'),
        loader.importLibrary('streetView'),
        loader.importLibrary('geocoding'),
        loader.importLibrary('places'),
        loader.importLibrary('routes'),
    ]).then(results => {
        const loadedLibraries = results
            .filter(result => result.status === 'fulfilled')
            .map(result => (result as PromiseFulfilledResult<any>).value);
        const failedLibraries = results.filter(
            result => result.status === 'rejected'
        );

        if (failedLibraries.length > 0) {
            if (retries === 0) {
                throw new Error(
                    `Failed to load ${failedLibraries.length} libraries after ${MAX_RETRIES} attempts.`
                );
            } else {
                return loadLibraries(loader, retries - 1);
            }
        }

        return loadedLibraries;
    });
};

const GoogleMapsProvider = ({apiKey, children}) => {
    const [googleMapsLoaded, setGoogleMapsLoaded] = useState(false);
    const [googleMapsLibraries, setGoogleMapsLibraries] = useState(null);

    useEffect(() => {
        let isCancelled = false;

        const loader = new Loader({
            apiKey,
            version: 'weekly',
        });

        loadLibraries(loader)
            .then(libs => {
                if (!isCancelled) {
                    setGoogleMapsLibraries({
                        core: libs[0],
                        maps: libs[1],
                        marker: libs[2],
                        streetView: libs[3],
                        geocoding: libs[4],
                        places: libs[5],
                        routes: libs[6],
                    });
                    setGoogleMapsLoaded(true);
                }
            })
            .catch(error => {
                console.error({
                    error,
                    message: 'GoogleMapsProvider: Error loading Google Maps libraries',
                });
            });

        return () => {
            isCancelled = true;
        };
    }, [apiKey]);

    if (typeof window === 'undefined') {
        return children;
    }

    return (
        <GoogleMapsContext.Provider
            value={{
                googleMapsLoaded,
                googleMapsLibraries,
            }}
        >
            {children}
        </GoogleMapsContext.Provider>
    );
};

const useGoogleMapsLibraries = () => {
    return useContext(GoogleMapsContext);
};

export {GoogleMapsProvider, useGoogleMapsLibraries};
wangela commented 5 months ago

If you would like to upvote the priority of this issue, please comment below or react on the original post above with :+1: so we can see what is popular when we triage.

@grusingh Thank you for opening this issue. 🙏 Please check out these other resources that might help you get to a resolution in the meantime:

This is an automated message, feel free to ignore.

awcs commented 5 months ago

Hello, i have the same issue with my users but only on Firefox. The error is random, it does not affect all users on Firefox and i cannot reproduce every time. Im using the library on a Vue3/Vite/PWA project.