CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-google-maps--api

React.js Google Maps API integration with components and hooks for seamless Google Maps functionality

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

layers.mddocs/

Layers

Layer components for displaying additional information overlays on the map including traffic data, transit routes, bicycling paths, heatmaps, and KML/KMZ files.

Capabilities

TrafficLayer Component

Displays real-time traffic information on the map with customizable styling and update intervals.

/**
 * Displays traffic information on the map
 * Shows real-time traffic conditions with color-coded congestion levels
 */
interface TrafficLayerProps {
  options?: google.maps.TrafficLayerOptions;
  
  // Lifecycle events
  onLoad?: (trafficLayer: google.maps.TrafficLayer) => void;
  onUnmount?: (trafficLayer: google.maps.TrafficLayer) => void;
}

function TrafficLayer(props: TrafficLayerProps): JSX.Element;

Usage Examples:

import React, { useState } from 'react';
import { GoogleMap, LoadScript, TrafficLayer } from '@react-google-maps/api';

// Basic traffic layer
function BasicTrafficLayer() {
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={13}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <TrafficLayer />
      </GoogleMap>
    </LoadScript>
  );
}

// Toggle traffic layer
function ToggleableTrafficLayer() {
  const [showTraffic, setShowTraffic] = useState(true);
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px' }}>
          <button onClick={() => setShowTraffic(!showTraffic)}>
            {showTraffic ? 'Hide' : 'Show'} Traffic
          </button>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={13}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {showTraffic && (
            <TrafficLayer 
              onLoad={() => console.log('Traffic layer loaded')}
            />
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

// Traffic layer with custom options
function CustomTrafficLayer() {
  const trafficOptions = {
    autoRefresh: true,
    // Additional traffic layer options can be configured here
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={13}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <TrafficLayer 
          options={trafficOptions}
          onLoad={(trafficLayer) => {
            console.log('Traffic layer loaded with options:', trafficOptions);
          }}
        />
      </GoogleMap>
    </LoadScript>
  );
}

TrafficLayerF Component

Functional component variant of TrafficLayer that uses React hooks internally.

/**
 * Functional variant of TrafficLayer component using hooks internally
 */
function TrafficLayerF(props: TrafficLayerProps): JSX.Element;

BicyclingLayer Component

Displays bicycling routes and bike-friendly paths on the map.

/**
 * Displays bicycling routes and paths on the map
 * Shows bike lanes, bike paths, and bike-friendly routes
 */
interface BicyclingLayerProps {
  // Lifecycle events
  onLoad?: (bicyclingLayer: google.maps.BicyclingLayer) => void;
  onUnmount?: (bicyclingLayer: google.maps.BicyclingLayer) => void;
}

function BicyclingLayer(props: BicyclingLayerProps): JSX.Element;

Usage Examples:

import React, { useState } from 'react';
import { GoogleMap, LoadScript, BicyclingLayer } from '@react-google-maps/api';

// Basic bicycling layer
function BasicBicyclingLayer() {
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={14}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <BicyclingLayer />
      </GoogleMap>
    </LoadScript>
  );
}

// Combined layers example
function CombinedTransportationLayers() {
  const [activeLayers, setActiveLayers] = useState({
    bicycling: true,
    traffic: false
  });
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px' }}>
          <label>
            <input
              type="checkbox"
              checked={activeLayers.bicycling}
              onChange={(e) => setActiveLayers(prev => ({
                ...prev,
                bicycling: e.target.checked
              }))}
            />
            Bicycling Routes
          </label>
          <label style={{ marginLeft: '20px' }}>
            <input
              type="checkbox"
              checked={activeLayers.traffic}
              onChange={(e) => setActiveLayers(prev => ({
                ...prev,
                traffic: e.target.checked
              }))}
            />
            Traffic
          </label>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={14}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {activeLayers.bicycling && (
            <BicyclingLayer 
              onLoad={() => console.log('Bicycling layer loaded')}
            />
          )}
          {activeLayers.traffic && (
            <TrafficLayer 
              onLoad={() => console.log('Traffic layer loaded')}
            />
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

BicyclingLayerF Component

Functional component variant of BicyclingLayer that uses React hooks internally.

/**
 * Functional variant of BicyclingLayer component using hooks internally
 */
function BicyclingLayerF(props: BicyclingLayerProps): JSX.Element;

TransitLayer Component

Displays public transit information including bus routes, subway lines, and transit stops.

/**
 * Displays public transit information on the map
 * Shows bus routes, subway lines, and transit stops
 */
interface TransitLayerProps {
  // Lifecycle events
  onLoad?: (transitLayer: google.maps.TransitLayer) => void;
  onUnmount?: (transitLayer: google.maps.TransitLayer) => void;
}

function TransitLayer(props: TransitLayerProps): JSX.Element;

Usage Examples:

import React, { useState } from 'react';
import { 
  GoogleMap, 
  LoadScript, 
  TransitLayer, 
  TrafficLayer, 
  BicyclingLayer 
} from '@react-google-maps/api';

// Basic transit layer
function BasicTransitLayer() {
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={13}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <TransitLayer />
      </GoogleMap>
    </LoadScript>
  );
}

// Multi-modal transportation layers
function MultiModalTransport() {
  const [layers, setLayers] = useState({
    transit: true,
    traffic: false,
    bicycling: false
  });
  
  const toggleLayer = (layerName: string) => {
    setLayers(prev => ({
      ...prev,
      [layerName]: !prev[layerName as keyof typeof prev]
    }));
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ 
          padding: '10px', 
          background: '#f5f5f5', 
          borderBottom: '1px solid #ddd' 
        }}>
          <h4 style={{ margin: '0 0 10px 0' }}>Transportation Layers</h4>
          
          <button
            onClick={() => toggleLayer('transit')}
            style={{
              marginRight: '10px',
              padding: '5px 10px',
              backgroundColor: layers.transit ? '#4285f4' : '#fff',
              color: layers.transit ? 'white' : '#333',
              border: '1px solid #4285f4',
              borderRadius: '4px',
              cursor: 'pointer'
            }}
          >
            Public Transit
          </button>
          
          <button
            onClick={() => toggleLayer('traffic')}
            style={{
              marginRight: '10px',
              padding: '5px 10px',
              backgroundColor: layers.traffic ? '#ea4335' : '#fff',
              color: layers.traffic ? 'white' : '#333',
              border: '1px solid #ea4335',
              borderRadius: '4px',
              cursor: 'pointer'
            }}
          >
            Traffic
          </button>
          
          <button
            onClick={() => toggleLayer('bicycling')}
            style={{
              padding: '5px 10px',
              backgroundColor: layers.bicycling ? '#34a853' : '#fff',
              color: layers.bicycling ? 'white' : '#333',
              border: '1px solid #34a853',
              borderRadius: '4px',
              cursor: 'pointer'
            }}
          >
            Bicycling
          </button>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={13}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {layers.transit && (
            <TransitLayer 
              onLoad={() => console.log('Transit layer loaded')}
            />
          )}
          {layers.traffic && (
            <TrafficLayer 
              onLoad={() => console.log('Traffic layer loaded')}
            />
          )}
          {layers.bicycling && (
            <BicyclingLayer 
              onLoad={() => console.log('Bicycling layer loaded')}
            />
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

TransitLayerF Component

Functional component variant of TransitLayer that uses React hooks internally.

/**
 * Functional variant of TransitLayer component using hooks internally
 */
function TransitLayerF(props: TransitLayerProps): JSX.Element;

HeatmapLayer Component

Displays data as a heatmap overlay with customizable appearance and data weighting options.

/**
 * Displays data as a heatmap overlay
 * Shows density and intensity of data points using color gradients
 */
interface HeatmapLayerProps {
  data: google.maps.LatLng[] | google.maps.visualization.WeightedLocation[];
  options?: google.maps.visualization.HeatmapLayerOptions;
  
  // Lifecycle events
  onLoad?: (heatmapLayer: google.maps.visualization.HeatmapLayer) => void;
  onUnmount?: (heatmapLayer: google.maps.visualization.HeatmapLayer) => void;
}

function HeatmapLayer(props: HeatmapLayerProps): JSX.Element;

Usage Examples:

import React, { useState, useMemo } from 'react';
import { GoogleMap, LoadScript, HeatmapLayer } from '@react-google-maps/api';

// Basic heatmap with random data
function BasicHeatmap() {
  const heatmapData = useMemo(() => {
    const data = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    
    // Generate random data points around NYC
    for (let i = 0; i < 100; i++) {
      data.push(new google.maps.LatLng(
        center.lat + (Math.random() - 0.5) * 0.1,
        center.lng + (Math.random() - 0.5) * 0.1
      ));
    }
    
    return data;
  }, []);
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY" libraries={['visualization']}>
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={12}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <HeatmapLayer data={heatmapData} />
      </GoogleMap>
    </LoadScript>
  );
}

// Weighted heatmap with custom styling
function WeightedHeatmap() {
  const [radius, setRadius] = useState(20);
  const [opacity, setOpacity] = useState(0.6);
  
  const weightedData = useMemo(() => {
    const locations = [
      { location: new google.maps.LatLng(40.7128, -74.0060), weight: 10 },
      { location: new google.maps.LatLng(40.7589, -73.9851), weight: 5 },
      { location: new google.maps.LatLng(40.7505, -73.9934), weight: 8 },
      { location: new google.maps.LatLng(40.7614, -73.9776), weight: 3 },
      { location: new google.maps.LatLng(40.7489, -73.9680), weight: 7 }
    ];
    
    // Add more random weighted points
    for (let i = 0; i < 50; i++) {
      locations.push({
        location: new google.maps.LatLng(
          40.7128 + (Math.random() - 0.5) * 0.08,
          -74.0060 + (Math.random() - 0.5) * 0.08
        ),
        weight: Math.random() * 5 + 1
      });
    }
    
    return locations;
  }, []);
  
  const heatmapOptions = {
    radius,
    opacity,
    gradient: [
      'rgba(0, 255, 255, 0)',
      'rgba(0, 255, 255, 1)',
      'rgba(0, 191, 255, 1)',
      'rgba(0, 127, 255, 1)',
      'rgba(0, 63, 255, 1)',
      'rgba(0, 0, 255, 1)',
      'rgba(0, 0, 223, 1)',
      'rgba(0, 0, 191, 1)',
      'rgba(0, 0, 159, 1)',
      'rgba(0, 0, 127, 1)',
      'rgba(63, 0, 91, 1)',
      'rgba(127, 0, 63, 1)',
      'rgba(191, 0, 31, 1)',
      'rgba(255, 0, 0, 1)'
    ]
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY" libraries={['visualization']}>
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <div style={{ marginBottom: '10px' }}>
            <label>
              Radius: {radius}
              <input
                type="range"
                min="10"
                max="50"
                value={radius}
                onChange={(e) => setRadius(parseInt(e.target.value))}
                style={{ marginLeft: '10px' }}
              />
            </label>
          </div>
          
          <div>
            <label>
              Opacity: {opacity.toFixed(1)}
              <input
                type="range"
                min="0.1"
                max="1"
                step="0.1"
                value={opacity}
                onChange={(e) => setOpacity(parseFloat(e.target.value))}
                style={{ marginLeft: '10px' }}
              />
            </label>
          </div>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={12}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          <HeatmapLayer 
            data={weightedData}
            options={heatmapOptions}
            onLoad={() => console.log('Heatmap loaded')}
          />
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

// Dynamic heatmap with data updates
function DynamicHeatmap() {
  const [dataPoints, setDataPoints] = useState<google.maps.visualization.WeightedLocation[]>([]);
  
  const addDataPoint = (lat: number, lng: number) => {
    const newPoint = {
      location: new google.maps.LatLng(lat, lng),
      weight: Math.random() * 10 + 1
    };
    
    setDataPoints(prev => [...prev, newPoint]);
  };
  
  const clearData = () => {
    setDataPoints([]);
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY" libraries={['visualization']}>
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <div>Data Points: {dataPoints.length}</div>
          <button 
            onClick={() => addDataPoint(
              40.7128 + (Math.random() - 0.5) * 0.05,
              -74.0060 + (Math.random() - 0.5) * 0.05
            )}
            style={{ marginRight: '10px' }}
          >
            Add Random Point
          </button>
          <button onClick={clearData}>
            Clear All
          </button>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={13}
          mapContainerStyle={{ width: '100%', height: '400px' }}
          onClick={(e) => {
            if (e.latLng) {
              addDataPoint(e.latLng.lat(), e.latLng.lng());
            }
          }}
        >
          {dataPoints.length > 0 && (
            <HeatmapLayer 
              data={dataPoints}
              options={{
                radius: 25,
                opacity: 0.7
              }}
            />
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

HeatmapLayerF Component

Functional component variant of HeatmapLayer that uses React hooks internally.

/**
 * Functional variant of HeatmapLayer component using hooks internally
 */
function HeatmapLayerF(props: HeatmapLayerProps): JSX.Element;

KmlLayer Component

Displays KML and KMZ files on the map with support for custom styling and interaction events.

/**
 * Displays KML and KMZ files on the map
 * Supports remote file loading and custom styling options
 */
interface KmlLayerProps {
  url: string;
  options?: google.maps.KmlLayerOptions;
  
  // Event handlers
  onClick?: (e: google.maps.KmlMouseEvent) => void;
  onDefaultViewportChanged?: () => void;
  onStatusChanged?: () => void;
  
  // Lifecycle events
  onLoad?: (kmlLayer: google.maps.KmlLayer) => void;
  onUnmount?: (kmlLayer: google.maps.KmlLayer) => void;
}

function KmlLayer(props: KmlLayerProps): JSX.Element;

Usage Examples:

import React, { useState } from 'react';
import { GoogleMap, LoadScript, KmlLayer } from '@react-google-maps/api';

// Basic KML layer
function BasicKmlLayer() {
  const kmlUrl = 'https://developers.google.com/maps/documentation/javascript/examples/kml/westcampus.kml';
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 37.4419, lng: -122.1419 }}
        zoom={13}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <KmlLayer
          url={kmlUrl}
          onLoad={() => console.log('KML layer loaded')}
          onClick={(e) => {
            console.log('KML feature clicked:', e.featureData);
          }}
        />
      </GoogleMap>
    </LoadScript>
  );
}

// Multiple KML layers with controls
function MultipleKmlLayers() {
  const [activeLayers, setActiveLayers] = useState({
    layer1: true,
    layer2: false,
    layer3: false
  });
  
  const kmlLayers = [
    {
      id: 'layer1',
      name: 'Campus Buildings',
      url: 'https://developers.google.com/maps/documentation/javascript/examples/kml/westcampus.kml'
    },
    {
      id: 'layer2', 
      name: 'Parking Areas',
      url: 'https://example.com/parking.kml'
    },
    {
      id: 'layer3',
      name: 'Walking Paths',
      url: 'https://example.com/paths.kml'
    }
  ];
  
  const toggleLayer = (layerId: string) => {
    setActiveLayers(prev => ({
      ...prev,
      [layerId]: !prev[layerId as keyof typeof prev]
    }));
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <h4>KML Layers</h4>
          {kmlLayers.map(layer => (
            <div key={layer.id} style={{ marginBottom: '5px' }}>
              <label>
                <input
                  type="checkbox"
                  checked={activeLayers[layer.id as keyof typeof activeLayers]}
                  onChange={() => toggleLayer(layer.id)}
                />
                {layer.name}
              </label>
            </div>
          ))}
        </div>
        
        <GoogleMap
          center={{ lat: 37.4419, lng: -122.1419 }}
          zoom={13}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {kmlLayers.map(layer => 
            activeLayers[layer.id as keyof typeof activeLayers] && (
              <KmlLayer
                key={layer.id}
                url={layer.url}
                options={{
                  suppressInfoWindows: false,
                  preserveViewport: true
                }}
                onLoad={() => console.log(`${layer.name} loaded`)}
                onClick={(e) => console.log(`${layer.name} feature clicked:`, e)}
                onStatusChanged={() => console.log(`${layer.name} status changed`)}
              />
            )
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

// KML layer with error handling
function KmlLayerWithErrorHandling() {
  const [kmlUrl, setKmlUrl] = useState('');
  const [layerStatus, setLayerStatus] = useState('');
  const [loadedLayer, setLoadedLayer] = useState<google.maps.KmlLayer | null>(null);
  
  const loadKmlFile = () => {
    if (!kmlUrl.trim()) {
      alert('Please enter a KML URL');
      return;
    }
    setLayerStatus('Loading...');
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <div style={{ marginBottom: '10px' }}>
            <input
              type="text"
              placeholder="Enter KML URL"
              value={kmlUrl}
              onChange={(e) => setKmlUrl(e.target.value)}
              style={{ width: '300px', marginRight: '10px' }}
            />
            <button onClick={loadKmlFile}>Load KML</button>
          </div>
          
          {layerStatus && (
            <div>Status: {layerStatus}</div>
          )}
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={10}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {kmlUrl && (
            <KmlLayer
              url={kmlUrl}
              onLoad={(kmlLayer) => {
                setLoadedLayer(kmlLayer);
                setLayerStatus('Loaded successfully');
                console.log('KML layer loaded:', kmlLayer.getUrl());
              }}
              onStatusChanged={() => {
                if (loadedLayer) {
                  const status = loadedLayer.getStatus();
                  setLayerStatus(`Status: ${status}`);
                  
                  if (status === google.maps.KmlLayerStatus.INVALID_DOCUMENT) {
                    setLayerStatus('Error: Invalid KML document');
                  } else if (status === google.maps.KmlLayerStatus.DOCUMENT_NOT_FOUND) {
                    setLayerStatus('Error: KML document not found');
                  } else if (status === google.maps.KmlLayerStatus.FETCH_ERROR) {
                    setLayerStatus('Error: Failed to fetch KML document');
                  }
                }
              }}
              onClick={(e) => {
                console.log('KML feature clicked:', {
                  featureData: e.featureData,
                  pixelOffset: e.pixelOffset
                });
              }}
            />
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

Layer Management Best Practices

Guidelines for effectively combining and managing multiple map layers.

/**
 * Best practices for layer management
 */
interface LayerManagerProps {
  children: React.ReactNode;
  maxConcurrentLayers?: number;
  onLayerLimitExceeded?: (layerCount: number) => void;
}

// Example layer management patterns
const LayerManager = ({ children, maxConcurrentLayers = 5 }: LayerManagerProps) => {
  const [activeLayers, setActiveLayers] = React.useState<string[]>([]);
  
  const addLayer = (layerId: string) => {
    if (activeLayers.length >= maxConcurrentLayers) {
      console.warn('Maximum layer limit reached');
      return false;
    }
    setActiveLayers(prev => [...prev, layerId]);
    return true;
  };
  
  const removeLayer = (layerId: string) => {
    setActiveLayers(prev => prev.filter(id => id !== layerId));
  };
  
  return <>{children}</>;
};

Layer Performance Examples:

// Optimized layer switching
function OptimizedLayerSwitching() {
  const [activeTransportLayer, setActiveTransportLayer] = useState<'traffic' | 'transit' | 'bicycling' | null>('traffic');
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY" libraries={['visualization']}>
      <div>
        <div style={{ padding: '10px' }}>
          <select 
            value={activeTransportLayer || ''} 
            onChange={(e) => setActiveTransportLayer(e.target.value as any || null)}
          >
            <option value="">No Transport Layer</option>
            <option value="traffic">Traffic</option>
            <option value="transit">Transit</option>
            <option value="bicycling">Bicycling</option>
          </select>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={13}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {activeTransportLayer === 'traffic' && <TrafficLayer />}
          {activeTransportLayer === 'transit' && <TransitLayer />}
          {activeTransportLayer === 'bicycling' && <BicyclingLayer />}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-react-google-maps--api

docs

clustering.md

core-map.md

drawing-shapes.md

index.md

layers.md

markers-overlays.md

places.md

script-loading.md

services.md

tile.json