Skip to content

Commit bbe5709

Browse files
authored
feat: add new onError prop for api provider (#541)
Add an optional prop onError to the APIProvider that will trigger if the Maps JavaScript API fails to load.
1 parent d82cf71 commit bbe5709

File tree

3 files changed

+54
-17
lines changed

3 files changed

+54
-17
lines changed

docs/api-reference/components/api-provider.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ A list of [libraries][gmp-libs] to load immediately
105105

106106
#### `solutionChannel`: string
107107

108-
To help Google to better understand types of usage of the Google Maps
109-
JavaScript API, the query parameter `solution_channel` can be set when
110-
loading the API.
108+
To help Google to better understand types of usage of the Google Maps
109+
JavaScript API, the query parameter `solution_channel` can be set when
110+
loading the API.
111111

112-
The `@vis.gl/react-google-maps` library will by default set
113-
this to a generic value unique to this library (`GMP_VISGL_react`). You may
112+
The `@vis.gl/react-google-maps` library will by default set
113+
this to a generic value unique to this library (`GMP_VISGL_react`). You may
114114
opt out at any time by setting this prop to an empty string.
115115
Read more in the [documentation][gmp-solutions-usage].
116116

@@ -121,6 +121,11 @@ Read more in the [documentation][gmp-solutions-usage].
121121
a callback that is called once the Maps JavaScript
122122
API finished loading.
123123

124+
#### `onError`: (error: unknown) => void {#onError}
125+
126+
a callback that is called if there is an error loading
127+
the Google Maps JavaScript API.
128+
124129
## Context
125130

126131
The APIProvider creates a context value `APIProviderContext` to be used by

src/components/__tests__/api-provider.test.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const ContextSpyComponent = () => {
2727
ContextSpyComponent.spy = jest.fn();
2828

2929
let triggerMapsApiLoaded: () => void;
30+
let triggerLoadingFailed: () => void;
3031

3132
jest.mock('../../libraries/google-maps-api-loader', () => {
3233
class GoogleMapsApiLoader {
@@ -38,14 +39,20 @@ jest.mock('../../libraries/google-maps-api-loader', () => {
3839
onLoadingStatusChange(APILoadingStatus.LOADING);
3940

4041
google.maps.importLibrary = importLibraryMock;
41-
return new Promise(
42-
resolve =>
43-
(triggerMapsApiLoaded = () => {
44-
resolve();
45-
onLoadingStatusChange(APILoadingStatus.LOADED);
46-
})
47-
);
42+
43+
return new Promise((resolve, reject) => {
44+
triggerLoadingFailed = () => {
45+
reject();
46+
onLoadingStatusChange(APILoadingStatus.FAILED);
47+
};
48+
49+
triggerMapsApiLoaded = () => {
50+
resolve();
51+
onLoadingStatusChange(APILoadingStatus.LOADED);
52+
};
53+
});
4854
}
55+
4956
static unload() {
5057
apiUnloadSpy();
5158
}
@@ -178,3 +185,13 @@ test('map instance management: add, access and remove', async () => {
178185
actualContext = contextSpy.mock.lastCall[0];
179186
expect(actualContext.mapInstances).toEqual({'map-id-2': map2});
180187
});
188+
189+
test('calls onError when loading the Google Maps JavaScript API fails', async () => {
190+
const onErrorMock = jest.fn();
191+
192+
render(<APIProvider apiKey={'apikey'} onError={onErrorMock}></APIProvider>);
193+
194+
await act(() => triggerLoadingFailed());
195+
196+
expect(onErrorMock).toHaveBeenCalled();
197+
});

src/components/api-provider.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ export type APIProviderProps = {
7979
* A function that can be used to execute code after the Google Maps JavaScript API has been loaded.
8080
*/
8181
onLoad?: () => void;
82+
/**
83+
* A function that will be called if there was an error when loading the Google Maps JavaScript API.
84+
*/
85+
onError?: (error: unknown) => void;
8286
};
8387

8488
/**
@@ -110,7 +114,14 @@ function useMapInstances() {
110114
* @param props
111115
*/
112116
function useGoogleMapsApiLoader(props: APIProviderProps) {
113-
const {onLoad, apiKey, version, libraries = [], ...otherApiParams} = props;
117+
const {
118+
onLoad,
119+
onError,
120+
apiKey,
121+
version,
122+
libraries = [],
123+
...otherApiParams
124+
} = props;
114125

115126
const [status, setStatus] = useState<APILoadingStatus>(
116127
GoogleMapsApiLoader.loadingStatus
@@ -176,10 +187,14 @@ function useGoogleMapsApiLoader(props: APIProviderProps) {
176187
onLoad();
177188
}
178189
} catch (error) {
179-
console.error(
180-
'<ApiProvider> failed to load the Google Maps JavaScript API',
181-
error
182-
);
190+
if (onError) {
191+
onError(error);
192+
} else {
193+
console.error(
194+
'<ApiProvider> failed to load the Google Maps JavaScript API',
195+
error
196+
);
197+
}
183198
}
184199
})();
185200
},

0 commit comments

Comments
 (0)