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

clustering.mddocs/

Marker Clustering

Components for grouping nearby markers into clusters to improve performance and user experience with large marker datasets. Includes both community and official Google clustering implementations, plus direct access to the Google Maps MarkerClusterer library.

Capabilities

MarkerClusterer Component

Community-driven marker clustering component that groups nearby markers into clusters for better performance and visual clarity.

/**
 * Groups nearby markers into clusters for better performance
 * Community implementation with extensive customization options
 */
interface MarkerClustererProps {
  children: React.ReactNode;
  options?: ClustererOptions;
  
  // Event handlers
  onClusteringBegin?: (clusterer: Clusterer) => void;
  onClusteringEnd?: (clusterer: Clusterer) => void;
  onClick?: (cluster: Cluster) => void;
  onMouseOver?: (cluster: Cluster) => void;
  onMouseOut?: (cluster: Cluster) => void;
  
  // Lifecycle events
  onLoad?: (clusterer: Clusterer) => void;
  onUnmount?: (clusterer: Clusterer) => void;
}

interface ClustererOptions {
  gridSize?: number;
  maxZoom?: number;
  zoomOnClick?: boolean;
  averageCenter?: boolean;
  minimumClusterSize?: number;
  styles?: ClusterIconStyle[];
  calculator?: (markers: google.maps.Marker[], numStyles: number) => ClusterIconInfo;
  ignoreHidden?: boolean;
  enableRetinaIcons?: boolean;
  imageExtension?: string;
  imagePath?: string;
  imageSizes?: number[];
  title?: string;
}

function MarkerClusterer(props: MarkerClustererProps): JSX.Element;
function MarkerClustererF(props: MarkerClustererProps): JSX.Element;

// Community clusterer type definitions
interface Clusterer {
  setAverageCenter(averageCenter: boolean): void;
  setBatchSizeIE(batchSizeIE: number): void;
  setCalculator(calculator: TCalculator): void;
  setClusterClass(clusterClass: string): void;
  setEnableRetinaIcons(enableRetinaIcons: boolean): void;
  setGridSize(gridSize: number): void;
  setIgnoreHidden(ignoreHidden: boolean): void;
  setImageExtension(imageExtension: string): void;
  setImagePath(imagePath: string): void;
  setImageSizes(imageSizes: number[]): void;
  setMaxZoom(maxZoom: number): void;
  setMinimumClusterSize(minimumClusterSize: number): void;
  setStyles(styles: ClusterIconStyle[]): void;
  setTitle(title: string): void;
  setZoomOnClick(zoomOnClick: boolean): void;
  addMarker(marker: google.maps.Marker, nodraw?: boolean): void;
  addMarkers(markers: google.maps.Marker[], nodraw?: boolean): void;
  clearMarkers(): void;
  getCalculator(): TCalculator;
  getGridSize(): number;
  getMap(): google.maps.Map;
  getMarkers(): google.maps.Marker[];
  getMaxZoom(): number;
  getStyles(): ClusterIconStyle[];
  getTotalClusters(): number;
  getTotalMarkers(): number;
}

interface Cluster {
  getCenter(): google.maps.LatLng;
  getSize(): number;
  getMarkers(): google.maps.Marker[];
}

interface ClusterIconInfo {
  text: string;
  index: number;
  title?: string;
}

type TCalculator = (markers: google.maps.Marker[], numStyles: number) => ClusterIconInfo;

Usage Examples:

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

// Basic marker clustering
function BasicMarkerClustering() {
  const markers = useMemo(() => {
    const locations = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    
    // Generate random markers around NYC
    for (let i = 0; i < 100; i++) {
      locations.push({
        id: i,
        position: {
          lat: center.lat + (Math.random() - 0.5) * 0.2,
          lng: center.lng + (Math.random() - 0.5) * 0.2
        }
      });
    }
    return locations;
  }, []);
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={10}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <MarkerClusterer>
          {markers.map(marker => (
            <Marker
              key={marker.id}
              position={marker.position}
            />
          ))}
        </MarkerClusterer>
      </GoogleMap>
    </LoadScript>
  );
}

// Custom clustering with styled clusters
function CustomStyledClustering() {
  const [clusterSize, setClusterSize] = useState(40);
  
  const markers = useMemo(() => {
    const locations = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    
    for (let i = 0; i < 200; i++) {
      locations.push({
        id: i,
        position: {
          lat: center.lat + (Math.random() - 0.5) * 0.3,
          lng: center.lng + (Math.random() - 0.5) * 0.3
        },
        title: `Marker ${i + 1}`
      });
    }
    return locations;
  }, []);
  
  const clusterOptions = {
    gridSize: clusterSize,
    styles: [
      {
        textColor: 'white',
        url: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m1.png',
        height: 53,
        width: 53
      },
      {
        textColor: 'white',
        url: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m2.png',
        height: 56,
        width: 56
      },
      {
        textColor: 'white',
        url: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m3.png',
        height: 66,
        width: 66
      }
    ],
    maxZoom: 15,
    zoomOnClick: true,
    averageCenter: true,
    minimumClusterSize: 2
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <label>
            Cluster Grid Size: {clusterSize}
            <input
              type="range"
              min="20"
              max="100"
              value={clusterSize}
              onChange={(e) => setClusterSize(parseInt(e.target.value))}
              style={{ marginLeft: '10px' }}
            />
          </label>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={10}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          <MarkerClusterer
            options={clusterOptions}
            onLoad={(clusterer) => console.log('Clusterer loaded')}
            onClick={(cluster) => console.log('Cluster clicked:', cluster.getSize())}
          >
            {markers.map(marker => (
              <Marker
                key={marker.id}
                position={marker.position}
                title={marker.title}
              />
            ))}
          </MarkerClusterer>
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

// Advanced clustering with custom calculator
function AdvancedClustering() {
  const [showClustering, setShowClustering] = useState(true);
  
  const markers = useMemo(() => {
    // Generate markers with different categories
    const categories = ['restaurant', 'hotel', 'attraction', 'shop'];
    const locations = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    
    for (let i = 0; i < 150; i++) {
      locations.push({
        id: i,
        position: {
          lat: center.lat + (Math.random() - 0.5) * 0.25,
          lng: center.lng + (Math.random() - 0.5) * 0.25
        },
        category: categories[Math.floor(Math.random() * categories.length)],
        rating: Math.floor(Math.random() * 5) + 1
      });
    }
    return locations;
  }, []);
  
  const customCalculator = (markers: google.maps.Marker[], numStyles: number) => {
    let index = 0;
    const count = markers.length;
    let dv = count;
    
    while (dv !== 0) {
      dv = Math.floor(dv / 10);
      index++;
    }
    
    index = Math.min(index, numStyles);
    
    return {
      text: count.toString(),
      index: index,
      title: `Cluster of ${count} markers`
    };
  };
  
  const clusterStyles = [
    {
      textColor: 'white',
      textSize: 12,
      url: 'data:image/svg+xml;base64,' + btoa(`
        <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40">
          <circle cx="20" cy="20" r="18" fill="#ff6b6b" stroke="white" stroke-width="2"/>
        </svg>
      `),
      height: 40,
      width: 40
    },
    {
      textColor: 'white',
      textSize: 14,
      url: 'data:image/svg+xml;base64,' + btoa(`
        <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
          <circle cx="25" cy="25" r="23" fill="#4285f4" stroke="white" stroke-width="2"/>
        </svg>
      `),
      height: 50,
      width: 50
    },
    {
      textColor: 'white',
      textSize: 16,
      url: 'data:image/svg+xml;base64,' + btoa(`
        <svg xmlns="http://www.w3.org/2000/svg" width="60" height="60">
          <circle cx="30" cy="30" r="28" fill="#34a853" stroke="white" stroke-width="2"/>
        </svg>
      `),
      height: 60,
      width: 60
    }
  ];
  
  const clusterOptions = {
    styles: clusterStyles,
    calculator: customCalculator,
    gridSize: 50,
    maxZoom: 14,
    zoomOnClick: true,
    averageCenter: true
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <label>
            <input
              type="checkbox"
              checked={showClustering}
              onChange={(e) => setShowClustering(e.target.checked)}
            />
            Enable Clustering ({markers.length} markers)
          </label>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={11}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {showClustering ? (
            <MarkerClusterer options={clusterOptions}>
              {markers.map(marker => (
                <Marker
                  key={marker.id}
                  position={marker.position}
                  title={`${marker.category} (Rating: ${marker.rating})`}
                  icon={`https://maps.google.com/mapfiles/ms/icons/${
                    marker.category === 'restaurant' ? 'red' :
                    marker.category === 'hotel' ? 'blue' :
                    marker.category === 'attraction' ? 'green' : 'yellow'
                  }-dot.png`}
                />
              ))}
            </MarkerClusterer>
          ) : (
            markers.map(marker => (
              <Marker
                key={marker.id}
                position={marker.position}
                title={`${marker.category} (Rating: ${marker.rating})`}
                icon={`https://maps.google.com/mapfiles/ms/icons/${
                  marker.category === 'restaurant' ? 'red' :
                  marker.category === 'hotel' ? 'blue' :
                  marker.category === 'attraction' ? 'green' : 'yellow'
                }-dot.png`}
              />
            ))
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

MarkerClustererF Component

Functional component variant of MarkerClusterer that uses React hooks internally.

/**
 * Functional variant of MarkerClusterer component using hooks internally
 */
function MarkerClustererF(props: MarkerClustererProps): JSX.Element;

GoogleMarkerClusterer Component

Official Google Maps marker clustering implementation with enhanced performance and features.

/**
 * Official Google marker clustering implementation
 * Enhanced performance and features compared to community version
 */
interface GoogleMarkerClustererProps {
  children: React.ReactNode;
  options?: google.maps.MarkerClustererOptions;
  
  // Event handlers
  onClusterClick?: (event: google.maps.MapMouseEvent, cluster: google.maps.markerclusterer.Cluster, map: google.maps.Map) => void;
  
  // Lifecycle events
  onLoad?: (clusterer: google.maps.MarkerClusterer) => void;
  onUnmount?: (clusterer: google.maps.MarkerClusterer) => void;
}

interface google.maps.MarkerClustererOptions {
  algorithm?: google.maps.markerclusterer.Algorithm;
  map?: google.maps.Map;
  markers?: google.maps.Marker[];
  renderer?: google.maps.markerclusterer.Renderer;
  onClusterClick?: (event: google.maps.MapMouseEvent, cluster: google.maps.markerclusterer.Cluster, map: google.maps.Map) => void;
}

function GoogleMarkerClusterer(props: GoogleMarkerClustererProps): JSX.Element;

Usage Examples:

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

// Basic Google marker clustering
function BasicGoogleClustering() {
  const markers = useMemo(() => {
    const locations = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    
    for (let i = 0; i < 1000; i++) {
      locations.push({
        id: i,
        position: {
          lat: center.lat + (Math.random() - 0.5) * 0.5,
          lng: center.lng + (Math.random() - 0.5) * 0.5
        }
      });
    }
    return locations;
  }, []);
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={9}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <GoogleMarkerClusterer
          onLoad={(clusterer) => console.log('Google clusterer loaded')}
          onClusterClick={(event, cluster, map) => {
            console.log('Cluster clicked:', cluster.count);
            map.fitBounds(cluster.bounds);
          }}
        >
          {markers.map(marker => (
            <Marker
              key={marker.id}
              position={marker.position}
            />
          ))}
        </GoogleMarkerClusterer>
      </GoogleMap>
    </LoadScript>
  );
}

// Google clustering with custom renderer
function CustomGoogleClustering() {
  const markers = useMemo(() => {
    const locations = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    
    for (let i = 0; i < 500; i++) {
      locations.push({
        id: i,
        position: {
          lat: center.lat + (Math.random() - 0.5) * 0.4,
          lng: center.lng + (Math.random() - 0.5) * 0.4
        },
        weight: Math.floor(Math.random() * 10) + 1
      });
    }
    return locations;
  }, []);
  
  // Custom renderer for cluster styling
  const createCustomRenderer = () => {
    return {
      render: ({ count, position }: { count: number; position: google.maps.LatLng }) => {
        const color = count > 100 ? '#ea4335' : count > 50 ? '#fbbc05' : '#34a853';
        const size = count > 100 ? 60 : count > 50 ? 50 : 40;
        
        const svg = `
          <svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
            <circle cx="${size/2}" cy="${size/2}" r="${size/2 - 2}" fill="${color}" stroke="white" stroke-width="2"/>
            <text x="${size/2}" y="${size/2}" text-anchor="middle" dy="0.3em" font-family="Arial" font-size="12" font-weight="bold" fill="white">
              ${count}
            </text>
          </svg>
        `;
        
        return new google.maps.Marker({
          position,
          icon: {
            url: `data:image/svg+xml;base64,${btoa(svg)}`,
            scaledSize: new google.maps.Size(size, size),
            anchor: new google.maps.Point(size / 2, size / 2)
          },
          label: {
            text: count.toString(),
            color: 'white',
            fontSize: '12px',
            fontWeight: 'bold'
          },
          zIndex: 1000 + count
        });
      }
    };
  };
  
  const clusterOptions = {
    renderer: createCustomRenderer(),
    // algorithm: new google.maps.markerclusterer.SuperClusterAlgorithm({
    //   radius: 100,
    //   maxZoom: 16
    // })
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        center={{ lat: 40.7128, lng: -74.0060 }}
        zoom={10}
        mapContainerStyle={{ width: '100%', height: '400px' }}
      >
        <GoogleMarkerClusterer
          options={clusterOptions}
          onLoad={(clusterer) => console.log('Custom Google clusterer loaded')}
          onClusterClick={(event, cluster, map) => {
            console.log('Custom cluster clicked:', cluster);
          }}
        >
          {markers.map(marker => (
            <Marker
              key={marker.id}
              position={marker.position}
              title={`Weight: ${marker.weight}`}
            />
          ))}
        </GoogleMarkerClusterer>
      </GoogleMap>
    </LoadScript>
  );
}

Clustering Performance Comparison

Performance comparison and recommendations for choosing between clustering implementations.

/**
 * Performance characteristics of different clustering approaches
 */
interface ClusteringPerformanceMetrics {
  markerCount: number;
  renderTime: number;
  memoryUsage: number;
  interactionLatency: number;
}

// Performance testing utility
const measureClusteringPerformance = (
  clusteringComponent: React.ReactElement,
  markerCount: number
): Promise<ClusteringPerformanceMetrics> => {
  // Implementation would measure actual performance metrics
  return Promise.resolve({
    markerCount,
    renderTime: 0,
    memoryUsage: 0,
    interactionLatency: 0
  });
};

Performance Comparison Examples:

// Side-by-side clustering comparison
function ClusteringComparison() {
  const [markerCount, setMarkerCount] = useState(100);
  const [activeMethod, setActiveMethod] = useState<'community' | 'google'>('community');
  
  const markers = useMemo(() => {
    const locations = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    
    for (let i = 0; i < markerCount; i++) {
      locations.push({
        id: i,
        position: {
          lat: center.lat + (Math.random() - 0.5) * 0.3,
          lng: center.lng + (Math.random() - 0.5) * 0.3
        }
      });
    }
    return locations;
  }, [markerCount]);
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <div style={{ marginBottom: '10px' }}>
            <label>
              Marker Count: {markerCount}
              <input
                type="range"
                min="50"
                max="2000"
                step="50"
                value={markerCount}
                onChange={(e) => setMarkerCount(parseInt(e.target.value))}
                style={{ marginLeft: '10px', width: '200px' }}
              />
            </label>
          </div>
          
          <div>
            <label style={{ marginRight: '20px' }}>
              <input
                type="radio"
                value="community"
                checked={activeMethod === 'community'}
                onChange={(e) => setActiveMethod(e.target.value as 'community')}
              />
              Community Clusterer
            </label>
            <label>
              <input
                type="radio"
                value="google"
                checked={activeMethod === 'google'}
                onChange={(e) => setActiveMethod(e.target.value as 'google')}
              />
              Google Clusterer
            </label>
          </div>
          
          <div style={{ marginTop: '10px', fontSize: '12px', color: '#666' }}>
            Recommendations:
            <ul style={{ margin: '5px 0', paddingLeft: '20px' }}>
              <li>Community: Better customization, lighter weight (&lt;1000 markers)</li>
              <li>Google: Better performance, official support (&gt;1000 markers)</li>
            </ul>
          </div>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={10}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          {activeMethod === 'community' ? (
            <MarkerClusterer
              options={{
                gridSize: 60,
                maxZoom: 15,
                zoomOnClick: true
              }}
            >
              {markers.map(marker => (
                <Marker key={marker.id} position={marker.position} />
              ))}
            </MarkerClusterer>
          ) : (
            <GoogleMarkerClusterer>
              {markers.map(marker => (
                <Marker key={marker.id} position={marker.position} />
              ))}
            </GoogleMarkerClusterer>
          )}
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

// Clustering with dynamic data loading
function DynamicClusteringExample() {
  const [markers, setMarkers] = useState<Array<{id: number, position: google.maps.LatLngLiteral}>>([]);
  const [isLoading, setIsLoading] = useState(false);
  
  const loadMoreMarkers = async (count: number) => {
    setIsLoading(true);
    
    // Simulate API call
    await new Promise(resolve => setTimeout(resolve, 1000));
    
    const newMarkers = [];
    const center = { lat: 40.7128, lng: -74.0060 };
    const startId = markers.length;
    
    for (let i = 0; i < count; i++) {
      newMarkers.push({
        id: startId + i,
        position: {
          lat: center.lat + (Math.random() - 0.5) * 0.5,
          lng: center.lng + (Math.random() - 0.5) * 0.5
        }
      });
    }
    
    setMarkers(prev => [...prev, ...newMarkers]);
    setIsLoading(false);
  };
  
  const clearMarkers = () => {
    setMarkers([]);
  };
  
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <div>
        <div style={{ padding: '10px', background: '#f0f0f0' }}>
          <div>Markers: {markers.length}</div>
          <button 
            onClick={() => loadMoreMarkers(100)}
            disabled={isLoading}
            style={{ marginRight: '10px' }}
          >
            {isLoading ? 'Loading...' : 'Add 100 Markers'}
          </button>
          <button 
            onClick={() => loadMoreMarkers(500)}
            disabled={isLoading}
            style={{ marginRight: '10px' }}
          >
            {isLoading ? 'Loading...' : 'Add 500 Markers'}
          </button>
          <button onClick={clearMarkers}>
            Clear All
          </button>
        </div>
        
        <GoogleMap
          center={{ lat: 40.7128, lng: -74.0060 }}
          zoom={9}
          mapContainerStyle={{ width: '100%', height: '400px' }}
        >
          <GoogleMarkerClusterer
            onLoad={(clusterer) => {
              console.log('Clusterer ready for', markers.length, 'markers');
            }}
          >
            {markers.map(marker => (
              <Marker
                key={marker.id}
                position={marker.position}
                title={`Marker ${marker.id}`}
              />
            ))}
          </GoogleMarkerClusterer>
        </GoogleMap>
      </div>
    </LoadScript>
  );
}

Clustering Best Practices

Guidelines for optimal clustering implementation and performance.

/**
 * Best practices for marker clustering implementation
 */
interface ClusteringBestPractices {
  // Performance optimization
  maxMarkersBeforeClustering: number;        // ~500-1000 markers
  optimalGridSize: number;                   // 40-80 pixels
  maxZoomForClustering: number;              // 15-17
  
  // Visual design
  clusterIconSizes: number[];                // [40, 50, 60] progressive sizes
  colorScheme: string[];                     // Consistent color progression
  textVisibility: boolean;                   // Always show count numbers
  
  // Interaction design
  zoomOnClusterClick: boolean;               // Usually true
  spiderfyOnClick: boolean;                  // For overlapping markers
  showClusterBounds: boolean;                // Debug/development only
}

// Example optimized clustering configuration
const optimizedClusterConfig = {
  community: {
    gridSize: 60,
    maxZoom: 15,
    zoomOnClick: true,
    averageCenter: true,
    minimumClusterSize: 2,
    styles: [
      { textColor: 'white', url: '/cluster-small.png', height: 40, width: 40 },
      { textColor: 'white', url: '/cluster-medium.png', height: 50, width: 50 },
      { textColor: 'white', url: '/cluster-large.png', height: 60, width: 60 }
    ]
  },
  google: {
    // Use default algorithm for best performance
    // Customize renderer for visual consistency
  }
};

GoogleMapsMarkerClusterer Namespace

Direct access to the official Google Maps MarkerClusterer library with all its classes, algorithms, and renderers.

GoogleMapsMarkerClusterer Namespace Export

Complete namespace re-export providing access to the official @googlemaps/markerclusterer library components.

/**
 * Complete namespace export of @googlemaps/markerclusterer
 * Provides direct access to Google's official clustering library
 */
import { GoogleMapsMarkerClusterer } from "@react-google-maps/api";

// Access to core MarkerClusterer class
class MarkerClusterer {
  constructor(options: {
    algorithm?: Algorithm;
    map?: google.maps.Map;
    markers?: google.maps.Marker[];
    renderer?: Renderer;
    onClusterClick?: onClusterClickHandler;
  });
  
  addMarker(marker: google.maps.Marker, noDraw?: boolean): void;
  addMarkers(markers: google.maps.Marker[], noDraw?: boolean): void;
  clearMarkers(noDraw?: boolean): void;
  render(): void;
  setMap(map: google.maps.Map | null): void;
}

// Access to clustering algorithms
interface Algorithm {
  calculate(request: AlgorithmInput): AlgorithmOutput;
}

// Access to cluster renderers  
interface Renderer {
  render(cluster: Cluster, stats: ClusterStats): google.maps.Marker;
}

// Cluster statistics for renderer
interface ClusterStats {
  count: number;
  markers: google.maps.Marker[];
}

// Event handler types
type onClusterClickHandler = (
  event: google.maps.MapMouseEvent,
  cluster: Cluster,
  map: google.maps.Map
) => void;

Usage Example:

import { GoogleMapsMarkerClusterer } from "@react-google-maps/api";

// Direct instantiation of Google's MarkerClusterer
function MyAdvancedClusteringComponent() {
  const map = useGoogleMap();
  
  React.useEffect(() => {
    if (map && markers.length > 0) {
      const markerClusterer = new GoogleMapsMarkerClusterer.MarkerClusterer({
        map,
        markers,
        onClusterClick: (event, cluster, map) => {
          map.fitBounds(cluster.bounds!);
        }
      });
      
      return () => markerClusterer.setMap(null);
    }
  }, [map, markers]);
  
  return null;
}

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