Google Map React is an isomorphic React component that allows rendering any React component on Google Maps. It provides a small wrapper over the Google Maps API that maintains full compatibility with server-side rendering, enabling maps to render even before the Google Maps API loads. The library features an internal hover algorithm for interactive map elements and supports custom React components as map markers.
npm install google-map-react or yarn add google-map-reactimport GoogleMapReact from 'google-map-react';For utility functions:
import GoogleMapReact, {
fitBounds,
convertNeSwToNwSe,
convertNwSeToNeSw,
meters2ScreenPixels,
tile2LatLng,
latLng2Tile,
getTilesIds
} from 'google-map-react';For CommonJS:
const GoogleMapReact = require('google-map-react').default;
const { fitBounds, convertNeSwToNwSe } = require('google-map-react');import React from 'react';
import GoogleMapReact from 'google-map-react';
const Marker = ({ text }) => <div>{text}</div>;
export default function SimpleMap() {
const defaultProps = {
center: {
lat: 59.955413,
lng: 30.337844
},
zoom: 11
};
return (
<div style={{ height: '100vh', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={defaultProps.center}
defaultZoom={defaultProps.zoom}
>
<Marker
lat={59.955413}
lng={30.337844}
text="My Marker"
/>
</GoogleMapReact>
</div>
);
}Google Map React is built around several key components:
The main GoogleMap React component with comprehensive props for map configuration, event handling, and child component management.
function GoogleMapReact(props: GoogleMapReactProps): JSX.Element;
interface GoogleMapReactProps {
// Required API configuration
bootstrapURLKeys: {
key: string;
language?: string;
region?: string;
libraries?: string[];
[key: string]: any;
};
// Position and zoom
center?: [number, number] | { lat: number; lng: number };
defaultCenter?: [number, number] | { lat: number; lng: number };
zoom?: number;
defaultZoom?: number;
// Event handlers
onClick?: (args: { x: number; y: number; lat: number; lng: number; event: MouseEvent }) => void;
onChange?: (args: { center: { lat: number; lng: number }; zoom: number; bounds: any; marginBounds?: any; size: { width: number; height: number } }) => void;
onBoundsChange?: (center: [number, number] | { lat: number; lng: number }, zoom: number, bounds: [number, number, number, number], marginBounds: [number, number, number, number]) => void;
onChildClick?: (childKey: any, childProps: any) => void;
onChildMouseDown?: (childKey: any, childProps: any, mouse: { x: number; y: number; lat: number; lng: number }) => void;
onChildMouseUp?: (childKey: any, childProps: any, mouse: { x: number; y: number; lat: number; lng: number }) => void;
onChildMouseMove?: (childKey: any, childProps: any, mouse: { x: number; y: number; lat: number; lng: number }) => void;
onChildMouseEnter?: (childKey: any, childProps: any) => void;
onChildMouseLeave?: (childKey: any, childProps: any) => void;
onZoomAnimationStart?: (zoomLevel: number) => void;
onZoomAnimationEnd?: (zoomLevel: number) => void;
onDrag?: (map: google.maps.Map) => void;
onDragEnd?: (map: google.maps.Map) => void;
onMapTypeIdChange?: (mapTypeId: string) => void;
onTilesLoaded?: () => void;
onGoogleApiLoaded?: (args: { map: google.maps.Map; maps: typeof google.maps; ref: HTMLDivElement }) => void;
// Configuration
options?: object | ((maps: typeof google.maps) => object);
style?: React.CSSProperties;
draggable?: boolean;
resetBoundsOnResize?: boolean;
yesIWantToUseGoogleMapApiInternals?: boolean;
// Hover system
distanceToMouse?: (pt: { x: number; y: number }, mousePos: { x: number; y: number }, markerProps: any) => number;
hoverDistance?: number;
debounced?: boolean;
margin?: [number, number, number, number];
// Advanced features
layerTypes?: Array<'TransitLayer' | 'TrafficLayer' | string>;
heatmap?: {
positions: Array<{ lat: number; lng: number; weight?: number }>;
options?: { [key: string]: any };
};
heatmapLibrary?: boolean;
shouldUnregisterMapOnUnmount?: boolean;
overlayViewDivStyle?: { [key: string]: any };
experimental?: boolean;
// Deprecated
apiKey?: string;
googleMapLoader?: any;
// Child component props (automatically passed)
children?: React.ReactNode;
}Functions for coordinate transformations, bounds calculations, and geographic computations.
function fitBounds(
bounds: { nw: { lat: number; lng: number }; se: { lat: number; lng: number } } |
{ ne: { lat: number; lng: number }; sw: { lat: number; lng: number } },
size: { width: number; height: number }
): { center: { lat: number; lng: number }; zoom: number; newBounds: any };
function meters2ScreenPixels(
meters: number,
center: { lat: number; lng: number },
zoom: number
): { w: number; h: number };
function convertNeSwToNwSe(bounds: {
ne: { lat: number; lng: number };
sw: { lat: number; lng: number }
}): { nw: { lat: number; lng: number }; se: { lat: number; lng: number } };
function convertNwSeToNeSw(bounds: {
nw: { lat: number; lng: number };
se: { lat: number; lng: number }
}): { ne: { lat: number; lng: number }; sw: { lat: number; lng: number } };Functions for working with map tiles and tile coordinates.
function tile2LatLng(tile: { x: number; y: number }, zoom: number): { lat: number; lng: number };
function latLng2Tile(coords: { lat: number; lng: number }, zoom: number): { x: number; y: number };
function getTilesIds(range: { from: { x: number; y: number }; to: { x: number; y: number } }, zoom: number): Array<[number, number, number]>;API for React components rendered as map markers with automatic positioning.
interface MapChildProps {
lat: number;
lng: number;
$hover?: boolean; // Automatically injected by GoogleMap
[key: string]: any; // Custom props
}Extended functionality including heatmaps, layers, overlay styling, and Google Maps API integration.
interface OverlayViewDivStyle {
[key: string]: any; // CSS properties for overlay div styling
}type LatLng = [number, number] | { lat: number; lng: number };
type Bounds = {
nw: { lat: number; lng: number };
se: { lat: number; lng: number };
} | {
ne: { lat: number; lng: number };
sw: { lat: number; lng: number };
};
interface Size {
width: number;
height: number;
}
interface Point {
x: number;
y: number;
}
interface FitBoundsResult {
center: { lat: number; lng: number };
zoom: number;
newBounds: {
nw: { lat: number; lng: number };
se: { lat: number; lng: number };
ne: { lat: number; lng: number };
sw: { lat: number; lng: number };
};
}