Skip to content

Instantly share code, notes, and snippets.

@baughmann
Created March 21, 2021 23:46
Show Gist options
  • Save baughmann/f999933a532d35642bbf7bbbae8351c7 to your computer and use it in GitHub Desktop.
Save baughmann/f999933a532d35642bbf7bbbae8351c7 to your computer and use it in GitHub Desktop.
A basic implementation of using the Google Maps JS API with a DrawingManager in React with TypeScript without relying on one of the amazing (but poorly maintained) libraries.
import { useEffect, useState } from "react";
interface IMapProps {
// so that the parent can get a reference to the google maps instance
onMapLoaded?: (next: google.maps.Map) => void;
// so that the parent can get a reference to
onDrawingManagerLoaded?: (next: google.maps.drawing.DrawingManager) => void;
className?: string;
}
const Map = (props: IMapProps) => {
const [map, setMap] = useState<google.maps.Map>();
const [
drawingManager,
setDrawingManager,
] = useState<google.maps.drawing.DrawingManager>();
// gets called after the Google Maps JS API is downloaded
const onScriptLoaded = () => {
setMap(
new window.google.maps.Map(document.getElementById("map")!!, {
center: { lat: -19.747778, lng: -47.931944 },
zoom: 12,
disableDefaultUI: true,
mapTypeId: "hybrid",
})
);
};
// inform the parent when the map gets loaded/reloaded
useEffect(() => props.onMapLoaded && map && props.onMapLoaded(map), [
map,
props.onMapLoaded,
]);
// inform the parent when the drawing manager gets loaded/reloaded
useEffect(
() =>
props.onDrawingManagerLoaded &&
drawingManager &&
props.onDrawingManagerLoaded(drawingManager),
[drawingManager, props.onDrawingManagerLoaded]
);
// watch for changes to the map instance and create a drawing manager
useEffect(() => {
if (map)
setDrawingManager(
new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: false,
map: map,
})
);
}, [map]);
// watch for window changes and add the script tag to the head
useEffect(() => {
if (!window.google) {
var s = document.createElement("script");
s.type = "text/javascript";
s.src = `https://maps.google.com/maps/api/js?key=<YOUR_API_KEY>&libraries=drawing`;
var x = document.getElementsByTagName("script")[0];
x.parentNode!!.insertBefore(s, x);
// Below is important.
//We cannot access google.maps until it's finished loading
s.addEventListener("load", onScriptLoaded);
} else {
onScriptLoaded();
}
}, []);
return <div className={props.className} id="map" style={{height: "500px", width: "500px"}} />;
};
export default Map;
{
"name": "agri",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"typescript": "^4.1.2",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@types/google.maps": "^3.44.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment