Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(example): use externally loaded google maps api #513

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions examples/external-js-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Externally loaded Google Maps JavaScript API

![image](https://user-images.githubusercontent.com/39244966/208682692-d5b23518-9e51-4a87-8121-29f71e41c777.png)

This is an example to show how to set up a simple Google map with the `<Map/>` with externally loaded Google Maps JavaScript API.
For instance, you can use the Google Maps JavaScript API URL to load the API when you need to use Client ID instead of API Key.

## Google Maps Platform API URL

This example does not come with an API URL. Running the examples locally requires a valid Google Maps JavaScript API URL.
See [the official documentation][get-load-maps-js-api] on how to create a URL.

The API URL has to be provided via an environment variable `GOOGLE_MAPS_API_URL`. This can be done by creating a
file named `.env` in the example directory with the following content:

```shell title=".env"
GOOGLE_MAPS_API_URL="<YOUR URL HERE>"
```

If you are on the CodeSandbox playground you can also choose to [provide the API URL like this](https://codesandbox.io/docs/learn/environment/secrets)

## Development

Go into the example-directory and run

```shell
npm install
```

To start the example with the local library run

```shell
npm run start-local
```

The regular `npm start` task is only used for the standalone versions of the example (CodeSandbox for example)

[get-load-maps-js-api]: https://developers.google.com/maps/documentation/javascript/load-maps-js-api#direct_script_loading_url_parameters
33 changes: 33 additions & 0 deletions examples/external-js-api/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>Externally loaded Google Maps JavaScript API</title>
<meta
name="description"
content="Externally loaded Google Maps JavaScript API Example" />
<style>
body {
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module">
import '@vis.gl/react-google-maps/examples.css';
import '@vis.gl/react-google-maps/examples.js';
import {renderToDom} from './src/app';

renderToDom(document.querySelector('#app'));
</script>
</body>
</html>
14 changes: 14 additions & 0 deletions examples/external-js-api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"type": "module",
"dependencies": {
"@vis.gl/react-google-maps": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"vite": "^5.0.4"
},
"scripts": {
"start": "vite",
"start-local": "vite --config ../vite.config.local.js",
"build": "vite build"
}
}
37 changes: 37 additions & 0 deletions examples/external-js-api/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import {createRoot} from 'react-dom/client';

import {APIProvider, Map} from '@vis.gl/react-google-maps';
import ControlPanel from './control-panel';
import {useExternallyLoadedMapsAPI} from './useExternallyLoadedMapsAPI';

const API_URL =
globalThis.GOOGLE_MAPS_API_URL ?? (process.env.GOOGLE_MAPS_API_URL as string);

const App = () => {
const isLoaded = useExternallyLoadedMapsAPI(API_URL);
return (
isLoaded && (
<APIProvider apiKey="">
<Map
defaultZoom={5}
defaultCenter={{lat: 42.54992, lng: 0}}
gestureHandling={'greedy'}
disableDefaultUI={true}
/>
<ControlPanel />
</APIProvider>
)
);
};
export default App;

export function renderToDom(container: HTMLElement) {
const root = createRoot(container);

root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
27 changes: 27 additions & 0 deletions examples/external-js-api/src/control-panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as React from 'react';

function ControlPanel() {
return (
<div className="control-panel">
<h3>Externally loaded Google Maps JavaScript API</h3>
<p>
The example demonstrates how to load the Google Maps API externally.
</p>
<div className="links">
<a
href="https://codesandbox.io/s/github/visgl/react-google-maps/tree/main/examples/external-js-api"
target="_new">
Try on CodeSandbox ↗
</a>

<a
href="https://github.com/visgl/react-google-maps/tree/main/examples/external-js-api"
target="_new">
View Code ↗
</a>
</div>
</div>
);
}

export default React.memo(ControlPanel);
44 changes: 44 additions & 0 deletions examples/external-js-api/src/useExternallyLoadedMapsAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {useEffect, useRef, useState} from 'react';

/**
* Simple hook to load an external Maps API script and check if it is loaded.
* @param {String} url - URL of the script to load.
*/
export function useExternallyLoadedMapsAPI(url: string) {
const [isLoaded, setIsLoaded] = useState(false);
const intervalRef = useRef<NodeJS.Timer | null>(null);
const scriptRef = useRef<HTMLScriptElement | null>(null);

useEffect(() => {
if (scriptRef.current?.src !== url) {
const script = document.createElement('script');
script.src = url;
script.async = true;
script.defer = true;
script.onload = () => {
// Validate if google.maps.importLibrary is loaded,
// it is not enough to check if window.google is loaded.maps
intervalRef.current = setInterval(() => {
if (window.google?.maps?.importLibrary as unknown) {
clearInterval(intervalRef.current as unknown as number);
setIsLoaded(true);
}
}, 10);
};

scriptRef.current = script;
document.head.appendChild(script);
}

return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current as unknown as number);
}
if (scriptRef.current) {
document.head.removeChild(scriptRef.current);
}
};
}, [url]);

return isLoaded;
}
17 changes: 17 additions & 0 deletions examples/external-js-api/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {defineConfig, loadEnv} from 'vite';

export default defineConfig(({}) => {
const {GOOGLE_MAPS_API_URL = ''} = loadEnv(mode, process.cwd(), '');

return {
define: {
'process.env.GOOGLE_MAPS_API_URL': JSON.stringify(GOOGLE_MAPS_API_URL)
},
resolve: {
alias: {
'@vis.gl/react-google-maps/examples.js':
'https://visgl.github.io/react-google-maps/scripts/examples.js'
}
}
};
});
3 changes: 2 additions & 1 deletion website/src/examples-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const sidebars = {
'directions',
'deckgl-overlay',
'map-3d',
'extended-component-library'
'extended-component-library',
'external-js-api',
]
}
]
Expand Down
5 changes: 5 additions & 0 deletions website/src/examples/external-js-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Deck.gl Overlay

import App from 'website-examples/external-js-api/src/app';

<App />