A step-by-step guide on incorporating MarkerClusterer into a google-map-react component

I am looking to integrate MarkerClusterer into my Google Map using a library or component. Here is a snippet of my current code. Can anyone provide guidance on how I can achieve this with the google-map-react library? Thank you.

const handleApiLoaded = ({ map, maps }: MapProps) => {
    console.log(maps);
    mapRef.current = { map, maps };
    if (truckData.length > 0) {
      const bounds = getBounds(maps);
      map.fitBounds(bounds);
      bindResizeListener(map, maps, bounds);
    }
};


 <GoogleMapReact
      bootstrapURLKeys={{ key: `${process.env.REACT_APP_GOOGLE_MAPS_KEY}` }}
      center={mapCenter}
      defaultZoom={14}
      options={{ zoomControlOptions: { position: 7 } }}
      layerTypes={isTraffic ? ["TrafficLayer"] : []}
      yesIWantToUseGoogleMapApiInternals
      onGoogleApiLoaded={handleApiLoaded}
    >
  </<GoogleMapReact>

interface MapProps {
  map: google.maps.Map;
  maps: {
    LatLngBounds: new () => google.maps.LatLngBounds;
  };

Could someone please assist me in implementing Marker Clustering with the google-map-react library? Thank you!

Answer №1

Successfully resolved the clustering issue by implementing the solution provided here

import React, {Component} from 'react'
import GoogleMapReact from 'google-map-react'
import MarkerClusterer from '@google/markerclusterer'

export default class GoogleMapContainer extends Component {
  componentDidMount () {
    const script = document.createElement('script')
    script.src = 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js'
    script.async = true
    document.body.appendChild(script)
  }

  setGoogleMapRef (map, maps) {
    this.googleMapRef = map
    this.googleRef = maps
    let locations = [
      {lat: -31.563910, lng: 147.154312},
      {lat: -33.718234, lng: 150.363181},
      {lat: -33.727111, lng: 150.371124}]
    let markers = locations && locations.map((location) => {
      return new this.googleRef.Marker({position: location})
    })
    let markerCluster = new MarkerClusterer(map, markers, {
      imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m',
      gridSize: 10,
      minimumClusterSize: 2
    })
  }

  static defaultProps = {
    center: {
      lat: 59.95,
      lng: 30.33
    },
    zoom: 11
  }

  render () {
    return (
      <GoogleMapReact
        bootstrapURLKeys={{key: `PLACE_HOLDER`}}
        yesIWantToUseGoogleMapApiInternals
        onGoogleApiLoaded={({map, maps}) => this.setGoogleMapRef(map, maps)}
        defaultCenter={{lat: -31.563910, lng: 147.154312}}
        defaultZoom={15}
        options={{streetViewControl: true}}
      />
    )
  }
}

view image description here

Answer №2

const setGoogleMapReference = ({ map, maps }: MapProps) => {
    mapRef.current = { map, maps };
    const markers =
      truckData &&
      truckData.map(data => {
        const latitude = data.coords.coordinates[0];
        const longitude = data.coords.coordinates[1];
        const location = { lat: latitude, lng: longitude };
        return new maps.Marker({ position: location });
      });
    const markerCluster = new MarkerClusterer(map, markers, {
      imagePath: "img/m1",
      gridSize: 30,
      minimumClusterSize: 5,
    });
  };

  useEffect(() => {
    if (mapRef.current) {
      const { map, maps } = mapRef.current;
    }
  }, [mapRef]);

  return (
    <GoogleMapReact
      bootstrapURLKeys={{ key: `${process.env.REACT_APP_GOOGLE_MAPS_KEY}` }}
      center={mapCenter}
      defaultZoom={14}
      options={{ zoomControlOptions: { position: 7 } }}
      layerTypes={isTraffic ? ["TrafficLayer"] : []}
      yesIWantToUseGoogleMapApiInternals
      onGoogleApiLoaded={setGoogleMapReference}
    >

I made a necessary addition with the useEffect for mapRef. Due to constraints with the provided images from https://github.com/googlemaps/v3-utility-library/tree/master/markerclusterer/images, I had to include them in the public/img folder. Appreciate your understanding.

Answer №3

import GoogleMap from "google-map-react";
import { MarkerClusterer } from "@googlemaps/markerclusterer";
import React from "react";

const handleApiLoaded = (map, maps) => {
  const markers = [];
  const infoWindows = [];

  const locations = [
    { lat: -31.56391, lng: 147.154312 },
    { lat: -33.718234, lng: 150.363181 },
    { lat: -33.727111, lng: 150.371124 },
  ];

  locations.forEach((location) => {
    markers.push(
      new maps.Marker({
        position: {
          lat: location.lat,
          lng: location.lng,
        },
        map,
      })
    );
  });

  new MarkerClusterer({ markers, map });
};
//Displaying Google Map using GoogleMap React library
function DisplayGoogleMap() {
  return (
    <GoogleMap
      defaultCenter={{ lat: -31.56391, lng: 147.154312 }}
      defaultZoom={15}
      bootstrapURLKeys={{ key: "keyCode" }}
      yesIWantToUseGoogleMapApiInternals
      onGoogleApiLoaded={({ map, maps }) => {
        handleApiLoaded(map, maps);
      }}
      options={{ streetViewControl: true }}
    />
  );
}

export default DisplayGoogleMap;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular2 - Breaking down applications into reusable components

Utilizing custom properties permits seamless data binding between multiple components. <section id="main"> <app-home [dict]="dict">Hello there!</app-home> </section> In this scenario, dict serves ...

What is the method to adjust the width of the popover in Material UI Autocomplete?

When working with Material-UI's Select component, you have the 'autoWidth' prop which adjusts the popover width based on the menu items. Is there a similar feature available for the Autocomplete component? I'm looking to set the TextF ...

struggling with configuring dependency injection in NestJS and TypeORM

Struggling with integrating nestjs and typeorm for a simple CRUD application, specifically facing issues with dependency injection. Attempting to modularize the database setup code and import it. Encountering this error message: [ExceptionHandler] Nest ...

Managing MUI form fields using React

It seems like I may be overlooking the obvious, as I haven't come across any other posts addressing the specific issue I'm facing. My goal is to provide an end user with the ability to set a location for an object either by entering information i ...

Can you explain the concept of being "well-typed" in TypeScript?

The website linked below discusses the compatibility of TypeScript 2.9 with well-defined JSON. What exactly does "well-typed" JSON mean? As far as I understand, JSON supports 6 valid data types: string, number, object, array, boolean, and null. Therefore, ...

Error: The function to create deep copies of objects is not working properly due to TypeError: Object(...) is not a

Encountering a TypeError: Object(...) is not a function in the following situation: To set up the state of a component with a specific Article (to be fetched from the backend in componentDidMount), I am implementing this approach // ArticlePage.tsx import ...

The exclude option in Nest JS middleware does not prevent the middleware from running on excluded routes

I'm having an issue with excluding certain routes from the middleware. The .exclude option doesn't seem to be working as expected, as the middleware is still being applied to the excluded routes. Here is the code for the Middleware: https://i.st ...

"Implementing automated default values for Select/dropdown lists in ReactJs, with the added capability to manually revert back to the default selection

After browsing multiple websites, I couldn't find a clear solution on how to both set and select a default value in a select element. Most resources only explain how to set the value, without addressing how to reselect the default value. My Requireme ...

Magical Stylist - Eradicate Indicators while Preserving Labeling

Recently, I've been experimenting with the Google styling wizard in an effort to remove markers while retaining labels for businesses. My objective is to eliminate the marker icons but still display the text labels such as "Jimmy Johns," "Boone Saloon ...

Utilize TypeScript to import a JSON file

I am trying to incorporate a JSON file using TypeScript, which contains data about different regions in Italy along with their respective capitals. Here is a snippet of the data: { "italia": [ { "regione": "Abruzzo", "capoluoghi": [ ...

Angular 14: Deleting an item from a FormArray triggers unintended form submission due to Angular animation

After beginning to create animations for my app, I observed that deleting an element from a FormArray triggers a form submission. Custom form controls were developed using ControlValueAccessor, and certain FormGroups are passed through @Inputs. The animati ...

Working with arrow functions in TypeScript syntax

I came across the following code snippet in TypeScript: (() => { const abc = 'blabla'; ... })(); Can someone explain what exactly this syntax means? I understand arrow functions in JS, so I get this: () => { const abc = &apos ...

Module '@tanstack/react-table' cannot be located even though it has been successfully installed

Currently, I am tackling a TypeScript React project and encountering an issue while attempting to import ColumnDef from @tanstack/react-table in my columns.tsx file. import { ColumnDef } from "@tanstack/react-table"; export type Payment = { id ...

There has been no answer provided. Could this be due to being utilized in an asynchronous function that was not returned as a promise?

I encountered the following error message: Error: No response has been set. Is this being used in an async call that was not returned as a promise to the intent handler? at DialogflowConversation.response (/user_code/node_modules/actions-on-google/dis ...

Guide: Populating an MUI Autocomplete TextField using data fetched from Axios

I have created a registration form for pets which includes an MUI Autocomplete component in the text field for selecting the pet type. However, I am facing an issue when trying to pre-fill the Autocomplete component with data from the database while edit ...

Leveraging Ionic 2 with Moment JS for Enhanced TimeZones

I am currently working on integrating moment.js with typescript. I have executed the following commands: npm install moment-timezone --save npm install @types/moment @types/moment-timezone --save However, when I use the formattime function, it appears th ...

Inheriting Angular components: How can the life cycle hooks of a parent component be triggered?

So I'm working with BaseComponent and a number of child components that extend it: export class Child1Component extends BaseComponent implements OnInit, AfterViewInit In the case of Child1Component, there is no explicit call to super.ngAfterViewInit ...

Updated the application to Angular 6 but encountered errors when attempting to run npm run build --prod. However, running the command npm run build --env=prod was executed without any issues

Running the command npm run build -- --prod results in the following error messages: 'PropertyName1' is private and can only be accessed within the 'AppComponent' class 'PropertyName2' does not exist in type 'AppCompo ...

The KeyConditionExpression is invalid due to the use of multiple attribute names within a single condition

I am trying to query a DynamoDB table using GraphQL TableName: "JobInfo", IndexName: "tableauGSI", KeyConditionExpression: "tableauGSI_Tableau = tableau AND #D BETWEEN :startDate AND :endDate", ExpressionAttributeNames: { "#D": "date" }, ...

Can components be SSGed individually rather than entire pages?

I am currently working with Next.js and I am wondering if there is a way to statically generate and display the database values in the header and footer components used across all pages. While getStaticProps can generate pages statically, it doesn't ...