React.js Google Maps API integration with components and hooks for seamless Google Maps functionality
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Service components for accessing Google Maps platform services including directions, distance matrix calculations, and Street View functionality with comprehensive routing and navigation capabilities.
Calculates routes between locations with support for multiple waypoints, travel modes, and routing preferences.
/**
* Calculates routes between locations
* Supports multiple waypoints, travel modes, and routing options
*/
interface DirectionsServiceProps {
options: google.maps.DirectionsRequest;
callback: (
result: google.maps.DirectionsResult | null,
status: google.maps.DirectionsStatus
) => void;
// Lifecycle events
onLoad?: (directionsService: google.maps.DirectionsService) => void;
onUnmount?: (directionsService: google.maps.DirectionsService) => void;
}
interface google.maps.DirectionsRequest {
destination: string | google.maps.LatLng | google.maps.LatLngLiteral | google.maps.Place;
origin: string | google.maps.LatLng | google.maps.LatLngLiteral | google.maps.Place;
avoidFerries?: boolean;
avoidHighways?: boolean;
avoidTolls?: boolean;
drivingOptions?: google.maps.DrivingOptions;
language?: string;
optimizeWaypoints?: boolean;
provideRouteAlternatives?: boolean;
region?: string;
transitOptions?: google.maps.TransitOptions;
travelMode?: google.maps.TravelMode;
unitSystem?: google.maps.UnitSystem;
waypoints?: google.maps.DirectionsWaypoint[];
}
function DirectionsService(props: DirectionsServiceProps): JSX.Element;Usage Examples:
import React, { useState } from 'react';
import {
GoogleMap,
LoadScript,
DirectionsService,
DirectionsRenderer
} from '@react-google-maps/api';
// Basic directions service
function BasicDirections() {
const [directionsResponse, setDirectionsResponse] = useState<google.maps.DirectionsResult | null>(null);
const [calculating, setCalculating] = useState(false);
const origin = { lat: 40.7128, lng: -74.0060 }; // NYC
const destination = { lat: 40.7589, lng: -73.9851 }; // Times Square
const directionsCallback = (
result: google.maps.DirectionsResult | null,
status: google.maps.DirectionsStatus
) => {
setCalculating(false);
if (status === 'OK' && result) {
setDirectionsResponse(result);
console.log('Directions calculated:', result);
} else {
console.error('Directions request failed:', status);
}
};
React.useEffect(() => {
setCalculating(true);
}, []);
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<GoogleMap
center={origin}
zoom={13}
mapContainerStyle={{ width: '100%', height: '400px' }}
>
{calculating && (
<DirectionsService
options={{
destination,
origin,
travelMode: google.maps.TravelMode.DRIVING
}}
callback={directionsCallback}
/>
)}
{directionsResponse && (
<DirectionsRenderer directions={directionsResponse} />
)}
</GoogleMap>
</LoadScript>
);
}
// Interactive directions with waypoints
function InteractiveDirections() {
const [directionsResponse, setDirectionsResponse] = useState<google.maps.DirectionsResult | null>(null);
const [waypoints, setWaypoints] = useState<google.maps.DirectionsWaypoint[]>([
{ location: { lat: 40.7505, lng: -73.9934 }, stopover: true }, // Empire State
{ location: { lat: 40.7614, lng: -73.9776 }, stopover: true } // Central Park
]);
const [travelMode, setTravelMode] = useState<google.maps.TravelMode>(google.maps.TravelMode.DRIVING);
const [calculating, setCalculating] = useState(false);
const calculateRoute = () => {
setCalculating(true);
setDirectionsResponse(null);
};
const directionsCallback = (
result: google.maps.DirectionsResult | null,
status: google.maps.DirectionsStatus
) => {
setCalculating(false);
if (status === 'OK' && result) {
setDirectionsResponse(result);
// Display route information
const route = result.routes[0];
const leg = route.legs[0];
console.log(`Distance: ${leg.distance?.text}, Duration: ${leg.duration?.text}`);
} else {
console.error('Directions failed:', status);
}
};
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<div>
<div style={{ padding: '10px', background: '#f0f0f0' }}>
<div style={{ marginBottom: '10px' }}>
<label>Travel Mode: </label>
<select
value={travelMode}
onChange={(e) => setTravelMode(e.target.value as google.maps.TravelMode)}
>
<option value={google.maps.TravelMode.DRIVING}>Driving</option>
<option value={google.maps.TravelMode.WALKING}>Walking</option>
<option value={google.maps.TravelMode.BICYCLING}>Bicycling</option>
<option value={google.maps.TravelMode.TRANSIT}>Transit</option>
</select>
</div>
<button
onClick={calculateRoute}
disabled={calculating}
style={{ marginRight: '10px' }}
>
{calculating ? 'Calculating...' : 'Calculate Route'}
</button>
<button onClick={() => setDirectionsResponse(null)}>
Clear Route
</button>
{directionsResponse && (
<div style={{ marginTop: '10px', fontSize: '14px' }}>
<div>Distance: {directionsResponse.routes[0]?.legs[0]?.distance?.text}</div>
<div>Duration: {directionsResponse.routes[0]?.legs[0]?.duration?.text}</div>
</div>
)}
</div>
<GoogleMap
center={{ lat: 40.7128, lng: -74.0060 }}
zoom={13}
mapContainerStyle={{ width: '100%', height: '400px' }}
>
{calculating && (
<DirectionsService
options={{
origin: { lat: 40.7128, lng: -74.0060 },
destination: { lat: 40.7589, lng: -73.9851 },
waypoints,
travelMode,
optimizeWaypoints: true,
avoidHighways: false,
avoidTolls: false
}}
callback={directionsCallback}
/>
)}
{directionsResponse && (
<DirectionsRenderer
directions={directionsResponse}
options={{
suppressMarkers: false,
suppressInfoWindows: false,
draggable: true
}}
/>
)}
</GoogleMap>
</div>
</LoadScript>
);
}
// Advanced directions with multiple options
function AdvancedDirections() {
const [directionsResponse, setDirectionsResponse] = useState<google.maps.DirectionsResult | null>(null);
const [routeOptions, setRouteOptions] = useState({
avoidHighways: false,
avoidTolls: false,
avoidFerries: false,
provideRouteAlternatives: true,
optimizeWaypoints: true
});
const directionsCallback = (
result: google.maps.DirectionsResult | null,
status: google.maps.DirectionsStatus
) => {
if (status === 'OK' && result) {
setDirectionsResponse(result);
// Log all available routes
result.routes.forEach((route, index) => {
console.log(`Route ${index + 1}:`, {
distance: route.legs[0]?.distance?.text,
duration: route.legs[0]?.duration?.text,
summary: route.summary
});
});
}
};
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<div>
<div style={{ padding: '10px', background: '#f0f0f0' }}>
<h4>Route Options</h4>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px' }}>
<label>
<input
type="checkbox"
checked={routeOptions.avoidHighways}
onChange={(e) => setRouteOptions(prev => ({
...prev,
avoidHighways: e.target.checked
}))}
/>
Avoid Highways
</label>
<label>
<input
type="checkbox"
checked={routeOptions.avoidTolls}
onChange={(e) => setRouteOptions(prev => ({
...prev,
avoidTolls: e.target.checked
}))}
/>
Avoid Tolls
</label>
<label>
<input
type="checkbox"
checked={routeOptions.avoidFerries}
onChange={(e) => setRouteOptions(prev => ({
...prev,
avoidFerries: e.target.checked
}))}
/>
Avoid Ferries
</label>
<label>
<input
type="checkbox"
checked={routeOptions.provideRouteAlternatives}
onChange={(e) => setRouteOptions(prev => ({
...prev,
provideRouteAlternatives: e.target.checked
}))}
/>
Show Alternatives
</label>
</div>
{directionsResponse && (
<div style={{ marginTop: '10px' }}>
<div>Found {directionsResponse.routes.length} route(s)</div>
{directionsResponse.routes.map((route, index) => (
<div key={index} style={{ fontSize: '12px', marginLeft: '10px' }}>
Route {index + 1}: {route.legs[0]?.distance?.text} - {route.legs[0]?.duration?.text}
</div>
))}
</div>
)}
</div>
<GoogleMap
center={{ lat: 40.7128, lng: -74.0060 }}
zoom={12}
mapContainerStyle={{ width: '100%', height: '400px' }}
>
<DirectionsService
options={{
origin: 'New York, NY',
destination: 'Philadelphia, PA',
travelMode: google.maps.TravelMode.DRIVING,
...routeOptions
}}
callback={directionsCallback}
/>
{directionsResponse && (
<DirectionsRenderer
directions={directionsResponse}
options={{
polylineOptions: {
strokeColor: '#4285f4',
strokeWeight: 6,
strokeOpacity: 0.8
}
}}
/>
)}
</GoogleMap>
</div>
</LoadScript>
);
}Displays calculated routes on the map with customizable styling and interaction options.
/**
* Displays calculated routes on the map
* Renders directions result with customizable styling and markers
*/
interface DirectionsRendererProps {
directions?: google.maps.DirectionsResult;
options?: google.maps.DirectionsRendererOptions;
panel?: HTMLElement;
routeIndex?: number;
// Event handlers
onDirectionsChanged?: () => void;
// Lifecycle events
onLoad?: (directionsRenderer: google.maps.DirectionsRenderer) => void;
onUnmount?: (directionsRenderer: google.maps.DirectionsRenderer) => void;
}
interface google.maps.DirectionsRendererOptions {
directions?: google.maps.DirectionsResult;
draggable?: boolean;
hideRouteList?: boolean;
infoWindow?: google.maps.InfoWindow;
markerOptions?: google.maps.MarkerOptions;
panel?: HTMLElement;
polylineOptions?: google.maps.PolylineOptions;
preserveViewport?: boolean;
routeIndex?: number;
suppressBicyclingLayer?: boolean;
suppressInfoWindows?: boolean;
suppressMarkers?: boolean;
suppressPolylines?: boolean;
}
function DirectionsRenderer(props: DirectionsRendererProps): JSX.Element;Usage Examples:
// Custom styled directions renderer
function StyledDirectionsRenderer() {
const [directionsResponse, setDirectionsResponse] = useState<google.maps.DirectionsResult | null>(null);
const [selectedRouteIndex, setSelectedRouteIndex] = useState(0);
const rendererOptions = {
suppressMarkers: false,
suppressInfoWindows: false,
draggable: true,
polylineOptions: {
strokeColor: '#ff6b6b',
strokeWeight: 8,
strokeOpacity: 0.8
},
markerOptions: {
icon: {
url: 'https://maps.google.com/mapfiles/ms/icons/red-dot.png',
scaledSize: new google.maps.Size(32, 32)
}
}
};
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<GoogleMap
center={{ lat: 40.7128, lng: -74.0060 }}
zoom={12}
mapContainerStyle={{ width: '100%', height: '400px' }}
>
<DirectionsService
options={{
origin: 'Times Square, New York',
destination: 'Central Park, New York',
travelMode: google.maps.TravelMode.WALKING,
provideRouteAlternatives: true
}}
callback={(result, status) => {
if (status === 'OK' && result) {
setDirectionsResponse(result);
}
}}
/>
{directionsResponse && (
<DirectionsRenderer
directions={directionsResponse}
routeIndex={selectedRouteIndex}
options={rendererOptions}
onLoad={(renderer) => console.log('Directions renderer loaded')}
/>
)}
</GoogleMap>
</LoadScript>
);
}Calculates travel distances and times between multiple origins and destinations with support for different travel modes.
/**
* Calculates travel distances and times between locations
* Supports multiple origins/destinations and different travel modes
*/
interface DistanceMatrixServiceProps {
options: google.maps.DistanceMatrixRequest;
callback: (
response: google.maps.DistanceMatrixResponse | null,
status: google.maps.DistanceMatrixStatus
) => void;
// Lifecycle events
onLoad?: (distanceMatrixService: google.maps.DistanceMatrixService) => void;
onUnmount?: (distanceMatrixService: google.maps.DistanceMatrixService) => void;
}
interface google.maps.DistanceMatrixRequest {
destinations: (string | google.maps.LatLng | google.maps.LatLngLiteral | google.maps.Place)[];
origins: (string | google.maps.LatLng | google.maps.LatLngLiteral | google.maps.Place)[];
avoidFerries?: boolean;
avoidHighways?: boolean;
avoidTolls?: boolean;
drivingOptions?: google.maps.DrivingOptions;
language?: string;
region?: string;
transitOptions?: google.maps.TransitOptions;
travelMode?: google.maps.TravelMode;
unitSystem?: google.maps.UnitSystem;
}
function DistanceMatrixService(props: DistanceMatrixServiceProps): JSX.Element;Usage Examples:
import React, { useState } from 'react';
import { GoogleMap, LoadScript, DistanceMatrixService } from '@react-google-maps/api';
// Distance matrix calculation
function DistanceMatrixExample() {
const [matrixResult, setMatrixResult] = useState<google.maps.DistanceMatrixResponse | null>(null);
const [calculating, setCalculating] = useState(false);
const origins = [
{ lat: 40.7128, lng: -74.0060 }, // NYC
{ lat: 40.7589, lng: -73.9851 } // Times Square
];
const destinations = [
{ lat: 40.7505, lng: -73.9934 }, // Empire State
{ lat: 40.7614, lng: -73.9776 }, // Central Park
{ lat: 40.6892, lng: -74.0445 } // Statue of Liberty
];
const calculateMatrix = () => {
setCalculating(true);
setMatrixResult(null);
};
const matrixCallback = (
response: google.maps.DistanceMatrixResponse | null,
status: google.maps.DistanceMatrixStatus
) => {
setCalculating(false);
if (status === 'OK' && response) {
setMatrixResult(response);
console.log('Distance matrix calculated:', response);
} else {
console.error('Distance matrix failed:', status);
}
};
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<div>
<div style={{ padding: '10px', background: '#f0f0f0' }}>
<button
onClick={calculateMatrix}
disabled={calculating}
style={{ marginBottom: '10px' }}
>
{calculating ? 'Calculating...' : 'Calculate Distance Matrix'}
</button>
{matrixResult && (
<div>
<h4>Distance Matrix Results</h4>
<table style={{ borderCollapse: 'collapse', width: '100%' }}>
<thead>
<tr>
<th style={{ border: '1px solid #ccc', padding: '5px' }}>Origin</th>
<th style={{ border: '1px solid #ccc', padding: '5px' }}>Destination</th>
<th style={{ border: '1px solid #ccc', padding: '5px' }}>Distance</th>
<th style={{ border: '1px solid #ccc', padding: '5px' }}>Duration</th>
</tr>
</thead>
<tbody>
{matrixResult.rows.map((row, originIndex) =>
row.elements.map((element, destIndex) => (
<tr key={`${originIndex}-${destIndex}`}>
<td style={{ border: '1px solid #ccc', padding: '5px' }}>
Origin {originIndex + 1}
</td>
<td style={{ border: '1px solid #ccc', padding: '5px' }}>
Destination {destIndex + 1}
</td>
<td style={{ border: '1px solid #ccc', padding: '5px' }}>
{element.distance?.text || 'N/A'}
</td>
<td style={{ border: '1px solid #ccc', padding: '5px' }}>
{element.duration?.text || 'N/A'}
</td>
</tr>
))
)}
</tbody>
</table>
</div>
)}
</div>
<GoogleMap
center={{ lat: 40.7128, lng: -74.0060 }}
zoom={12}
mapContainerStyle={{ width: '100%', height: '400px' }}
>
{calculating && (
<DistanceMatrixService
options={{
origins,
destinations,
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}}
callback={matrixCallback}
/>
)}
</GoogleMap>
</div>
</LoadScript>
);
}
// Travel time comparison across modes
function TravelModeComparison() {
const [results, setResults] = useState<{[key: string]: google.maps.DistanceMatrixResponse}>({});
const [calculating, setCalculating] = useState<{[key: string]: boolean}>({});
const travelModes = [
{ key: 'driving', mode: google.maps.TravelMode.DRIVING, name: 'Driving' },
{ key: 'walking', mode: google.maps.TravelMode.WALKING, name: 'Walking' },
{ key: 'bicycling', mode: google.maps.TravelMode.BICYCLING, name: 'Bicycling' },
{ key: 'transit', mode: google.maps.TravelMode.TRANSIT, name: 'Transit' }
];
const calculateForMode = (modeKey: string, travelMode: google.maps.TravelMode) => {
setCalculating(prev => ({ ...prev, [modeKey]: true }));
};
const createCallback = (modeKey: string) => (
response: google.maps.DistanceMatrixResponse | null,
status: google.maps.DistanceMatrixStatus
) => {
setCalculating(prev => ({ ...prev, [modeKey]: false }));
if (status === 'OK' && response) {
setResults(prev => ({ ...prev, [modeKey]: response }));
}
};
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<div>
<div style={{ padding: '10px', background: '#f0f0f0' }}>
<h4>Travel Mode Comparison: NYC to Times Square</h4>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '10px', marginBottom: '20px' }}>
{travelModes.map(({ key, mode, name }) => (
<button
key={key}
onClick={() => calculateForMode(key, mode)}
disabled={calculating[key]}
style={{ padding: '10px' }}
>
{calculating[key] ? 'Calculating...' : `Calculate ${name}`}
</button>
))}
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '20px' }}>
{travelModes.map(({ key, name }) => (
<div key={key} style={{ background: 'white', padding: '10px', borderRadius: '4px' }}>
<h5>{name}</h5>
{results[key] ? (
<div>
<div>Distance: {results[key].rows[0]?.elements[0]?.distance?.text}</div>
<div>Duration: {results[key].rows[0]?.elements[0]?.duration?.text}</div>
</div>
) : (
<div>No data</div>
)}
</div>
))}
</div>
</div>
<GoogleMap
center={{ lat: 40.7128, lng: -74.0060 }}
zoom={13}
mapContainerStyle={{ width: '100%', height: '300px' }}
>
{Object.entries(calculating).map(([modeKey, isCalculating]) =>
isCalculating && (
<DistanceMatrixService
key={modeKey}
options={{
origins: [{ lat: 40.7128, lng: -74.0060 }],
destinations: [{ lat: 40.7589, lng: -73.9851 }],
travelMode: travelModes.find(m => m.key === modeKey)?.mode || google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL
}}
callback={createCallback(modeKey)}
/>
)
)}
</GoogleMap>
</div>
</LoadScript>
);
}Provides access to Street View imagery and metadata for locations with panoramic photo availability.
/**
* Access to Street View imagery and metadata
* Provides information about available Street View panoramas
*/
interface StreetViewServiceProps {
// Lifecycle events
onLoad?: (streetViewService: google.maps.StreetViewService) => void;
onUnmount?: (streetViewService: google.maps.StreetViewService) => void;
}
function StreetViewService(props: StreetViewServiceProps): JSX.Element;Displays Street View panoramas with navigation controls and customizable viewing options.
/**
* Displays Street View panoramas
* Interactive panoramic street-level imagery with navigation
*/
interface StreetViewPanoramaProps {
options?: google.maps.StreetViewPanoramaOptions;
// Event handlers
onCloseClick?: () => void;
onPanoChanged?: () => void;
onPositionChanged?: () => void;
onPovChanged?: () => void;
onResize?: () => void;
onStatusChanged?: () => void;
onVisibleChanged?: () => void;
onZoomChanged?: () => void;
// Lifecycle events
onLoad?: (streetViewPanorama: google.maps.StreetViewPanorama) => void;
onUnmount?: (streetViewPanorama: google.maps.StreetViewPanorama) => void;
}
function StreetViewPanorama(props: StreetViewPanoramaProps): JSX.Element;Usage Examples:
// Street View integration
function StreetViewExample() {
const [streetViewPosition, setStreetViewPosition] = useState({ lat: 40.7128, lng: -74.0060 });
const [streetViewVisible, setStreetViewVisible] = useState(false);
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<div>
<div style={{ padding: '10px', background: '#f0f0f0' }}>
<button
onClick={() => setStreetViewVisible(!streetViewVisible)}
style={{ marginBottom: '10px' }}
>
{streetViewVisible ? 'Hide' : 'Show'} Street View
</button>
</div>
<div style={{ display: 'flex', height: '400px' }}>
<GoogleMap
center={streetViewPosition}
zoom={15}
mapContainerStyle={{ width: '50%', height: '100%' }}
onClick={(e) => {
if (e.latLng) {
setStreetViewPosition(e.latLng.toJSON());
}
}}
/>
{streetViewVisible && (
<div style={{ width: '50%' }}>
<StreetViewPanorama
options={{
position: streetViewPosition,
pov: { heading: 34, pitch: 10 },
zoom: 1,
visible: true
}}
onLoad={(panorama) => console.log('Street View loaded')}
onPositionChanged={() => console.log('Street View position changed')}
/>
</div>
)}
</div>
</div>
</LoadScript>
);
}Common patterns for combining multiple Google Maps services effectively.
/**
* Service integration patterns and best practices
*/
interface ServiceIntegrationPatterns {
// Sequential service calls
sequentialServices: boolean; // Avoid simultaneous heavy requests
// Caching strategies
cacheResults: boolean; // Cache directions/distance results
cacheTimeout: number; // Cache expiration time
// Error handling
retryOnFailure: boolean; // Retry failed requests
maxRetries: number; // Maximum retry attempts
fallbackBehavior: string; // Behavior when services fail
}
// Example service orchestration
const ServiceOrchestrator = {
async calculateRouteWithAlternatives(origin: string, destination: string) {
// 1. Get directions
const directions = await this.getDirections(origin, destination);
// 2. Calculate distance matrix for comparison
const matrix = await this.getDistanceMatrix([origin], [destination]);
// 3. Check Street View availability at key points
const streetViewAvailable = await this.checkStreetView(destination);
return {
directions,
matrix,
streetViewAvailable
};
}
};Install with Tessl CLI
npx tessl i tessl/npm-react-google-maps--api