Show All Cluster Markers in react-leaflet-markerclusterer using React Typescript

My React Typescript app is displaying a Leaflet map with marker clusters using react-leaflet & react-leaflet-markerclusterer.

However, I am unable to get the map to show all cluster markers inside the map view. I am attempting to convert this JS solution to Typescript.

One of the errors shown in the. JS console is

React Hook "useMap" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function

In VSCode, there is also a Typescript error

Object is possibly ‘undefined’.ts(2532)

on the line

const groupBounds = group.getBounds();

Why is this happening, and what is the proper way to write this Typescript code?

import React, { useEffect, useRef } from 'react';
import { MapContainer, TileLayer, Marker, useMap } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';

interface IProps {
    markers: {
        lat: number;
        lon: number;
    }[];
    
    mapCenter: {
        lat: number;
        lon: number;
    };
}

export function MapView({markers, mapCenter}: IProps): JSX.Element {

    const groupRef = useRef();
    
    useEffect(() => {
        if (groupRef !== undefined) {
            const group = groupRef.current;
            const map = useMap();                   // ERROR: React Hook "useMap" cannot be called inside a callback.
            const groupBounds = group.getBounds();  // ERROR: Object is possibly 'undefined'.ts(2532)
            map.fitBounds(groupBounds);
        }
    }, []);

    return (
        <MapContainer
            center={[mapCenter.lat, mapCenter.lon]}
            zoom={10}
            style={{ width:'100%', height:'100vh' }}
            className='markercluster-map'
        >
            <TileLayer 
                url={`https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=${access_token}`}
            />
            <MarkerClusterGroup ref={groupRef}>
                {
                    markers.map((marker, index) => (
                        <Marker 
                            position={[marker.lat, marker.lon]} 
                            key={index}
                        />
                    ))
                }
            </MarkerClusterGroup>
        </MapContainer>
    )
}

Leave a Comment