Skip to content

SuperClusterAlgorithm Properties Not Accessible in Renderer #1068

@ops295

Description

@ops295

SuperClusterAlgorithm Properties Not Accessible in Renderer

Issue Description

When using SuperClusterAlgorithm with custom map and reduce functions in @googlemaps/markerclusterer, the aggregated properties computed by the algorithm are not accessible in the renderer function. The cluster object passed to the renderer does not contain the properties that were calculated and returned by the algorithm's map/reduce functions.

Expected Behavior

The aggregated properties computed by SuperCluster's map/reduce functions should be accessible in the renderer, either:

  1. Through cluster.markers[0].properties
  2. Through the stats parameter
  3. Through some other documented mechanism

Actual Behavior

  • cluster.markers[0].properties is undefined
  • stats parameter doesn't contain the aggregated properties
  • No way to access the computed aggregation data in the renderer

Reproduction Code

import { SuperClusterAlgorithm, MarkerClusterer } from '@googlemaps/markerclusterer';

// Define aggregated properties interface
interface AggregatedProps {
  total_assets: number;
  asset_type_counts: Record<string, number>;
  selected_count: number;
  status_counts: Record<string, number>;
  most_severe_status: string;
}

// Create SuperCluster algorithm with map/reduce functions
const algorithm = new SuperClusterAlgorithm({
  maxZoom: 22,
  radius: 80,
  
  // MAP: Process individual markers
  map: (props) => {
    const aggregated: AggregatedProps = {
      total_assets: 1,
      asset_type_counts: { [props.assetType]: 1 },
      selected_count: props.isSelected ? 1 : 0,
      status_counts: { [props.status]: 1 },
      most_severe_status: props.status,
    };
    console.log('MAP function returning:', aggregated);
    return aggregated;
  },

  // REDUCE: Merge properties of clusters
  reduce: (accumulated, props) => {
    accumulated.total_assets += props.total_assets;
    
    // Merge asset type counts
    for (const type in props.asset_type_counts) {
      accumulated.asset_type_counts[type] = 
        (accumulated.asset_type_counts[type] || 0) + props.asset_type_counts[type];
    }
    
    // Merge other properties...
    accumulated.selected_count += props.selected_count;
    
    console.log('REDUCE function result:', accumulated);
  },
});

// Custom renderer that should access aggregated properties
const renderer = {
  render: (cluster, stats, map) => {
    console.log('Renderer cluster:', cluster);
    console.log('Renderer stats:', stats);
    console.log('Cluster markers:', cluster.markers);
    console.log('First marker properties:', cluster.markers[0]?.properties);
    
    // ❌ These are all undefined:
    // - cluster.markers[0].properties
    // - stats.properties  
    // - stats (doesn't contain our aggregated data)
    
    // Expected: Access to AggregatedProps computed by map/reduce
    // Actual: No access to computed aggregation data
    
    // Create marker without access to aggregated data
    return new google.maps.Marker({
      position: cluster.position,
      label: String(cluster.count), // Can only use basic cluster.count
    });
  }
};

// Initialize clusterer
const clusterer = new MarkerClusterer({
  map: googleMap,
  algorithm: algorithm,
  renderer: renderer,
});

Console Output

MAP function returning: { total_assets: 1, asset_type_counts: {...}, ... }
REDUCE function result: { total_assets: 5, asset_type_counts: {...}, ... }
Renderer cluster: { count: 5, position: {...}, markers: [...] }
Renderer stats: { ... } // Basic stats, no custom properties
Cluster markers: [Marker, Marker, Marker, Marker, Marker]
First marker properties: undefined

Environment

  • @googlemaps/markerclusterer: ^2.5.3
  • TypeScript: ^5.0.0
  • Browser: Chrome 118+

Workaround

Currently having to manually re-aggregate data in the renderer by processing cluster.markers, which defeats the purpose of using SuperCluster's efficient map/reduce aggregation:

const renderer = {
  render: (cluster, stats, map) => {
    // Manual re-aggregation (inefficient)
    const clusterAssets = cluster.markers.map(getAssetFromMarker);
    const manuallyAggregated = {
      total_assets: clusterAssets.length,
      selected_count: clusterAssets.filter(a => a.isSelected).length,
      // ... re-compute everything the algorithm already computed
    };
    
    // Use manually aggregated data for rendering
    return createMarkerWithAggregatedData(manuallyAggregated);
  }
};

Suggested Fix

The renderer should have access to the aggregated properties, ideally through one of these approaches:

  1. Option 1: cluster.properties containing the aggregated data
  2. Option 2: cluster.markers[0].properties containing the aggregated data
  3. Option 3: stats parameter containing the aggregated data
  4. Option 4: Additional parameter with aggregated data

Related Documentation

Could not find documentation on how to access custom properties computed by SuperCluster's map/reduce functions in the MarkerClusterer renderer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage meI really want to be triaged.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions