React Leaflet Markercluster
react-leaflet-markercluster is a dedicated React component that provides an intuitive wrapper for the popular Leaflet.markercluster plugin, designed specifically for use within react-leaflet applications. It addresses the common challenge of visualizing a large number of markers on a map by dynamically grouping them into clusters at various zoom levels, preventing clutter and improving map performance and user experience. The current stable release is v4.2.1, with v5.0.0-rc.0 currently in a release candidate phase to support React 19 and react-leaflet v5. The package aims for stability and compatibility with major react-leaflet versions, often releasing new major versions to align with its peer dependencies. Its primary differentiator is its seamless integration into the react-leaflet ecosystem, allowing developers to simply wrap existing Leaflet Marker components within a `<MarkerClusterGroup />` to enable clustering functionality without complex imperative Leaflet API calls, while also exposing full control over Leaflet.markercluster options via component props.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'addLayer')
cause Leaflet or Leaflet.markercluster is not correctly initialized or available globally (e.g., L is not defined) before react-leaflet-markercluster attempts to use it.fixEnsure `leaflet` and `leaflet.markercluster` peer dependencies are installed and properly imported/configured in your project before rendering React components that depend on them. -
MarkerClusterGroup is not a function or a valid JSX element.
cause Incorrect import of `MarkerClusterGroup`, commonly by attempting to use a named import (`{ MarkerClusterGroup }`) instead of a default import, or using CJS `require` in a modern ESM context.fixVerify your import statement to be `import MarkerClusterGroup from 'react-leaflet-markercluster';`. -
Map is not visible or marker clusters are not styled correctly (e.g., default blue Leaflet markers instead of clusters).
cause Required CSS stylesheets for Leaflet and/or react-leaflet-markercluster are not loaded into the browser.fixAdd `import 'leaflet/dist/leaflet.css';` and `import 'react-leaflet-markercluster/styles';` to your application's entry point (e.g., `App.tsx` or `index.ts`) or include them via HTML `<link>` tags.
Warnings
- breaking Major version 5.x introduces breaking changes for compatibility with React 19 and react-leaflet 5. This requires upgrading your entire React-Leaflet ecosystem.
- breaking The MarkerClusterGroup component removed direct support for 'marker' object 'lat' and 'lng' keys. Marker positions must now be provided via the 'position' key.
- breaking The 'options' property on MarkerClusterGroup was removed. All Leaflet.markercluster options should be passed directly as props to the component.
- gotcha Stylesheets for both Leaflet and react-leaflet-markercluster must be correctly imported for the map and clustering to render properly and visibly.
- gotcha The package relies on `leaflet.markercluster` as a peer dependency, which must be installed alongside `react-leaflet-markercluster`.
Install
-
npm install react-leaflet-markercluster -
yarn add react-leaflet-markercluster -
pnpm add react-leaflet-markercluster
Imports
- MarkerClusterGroup
import { MarkerClusterGroup } from 'react-leaflet-markercluster'; const MarkerClusterGroup = require('react-leaflet-markercluster');import MarkerClusterGroup from 'react-leaflet-markercluster';
- Styles
import 'react-leaflet-markercluster/dist/styles.css';
import 'react-leaflet-markercluster/styles';
- MarkerClusterGroupProps (Type)
import { MarkerClusterGroupProps } from 'react-leaflet-markercluster';import type { MarkerClusterGroupProps } from 'react-leaflet-markercluster';
Quickstart
import React from 'react';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';
// Ensure Leaflet and MarkerClusterGroup styles are loaded
import 'leaflet/dist/leaflet.css';
import 'react-leaflet-markercluster/styles';
function MyMapComponent() {
const markers = [
{ position: [49.8397, 24.0297], id: 1, name: 'Lviv' },
{ position: [52.2297, 21.0122], id: 2, name: 'Warsaw' },
{ position: [51.5074, -0.0901], id: 3, name: 'London' },
{ position: [50.0880, 14.4208], id: 4, name: 'Prague' },
{ position: [48.8566, 2.3522], id: 5, name: 'Paris' },
{ position: [40.7128, -74.0060], id: 6, name: 'New York' },
{ position: [34.0522, -118.2437], id: 7, name: 'Los Angeles' },
{ position: [35.6895, 139.6917], id: 8, name: 'Tokyo' }
];
return (
<MapContainer
className="markercluster-map"
center={[51.0, 19.0]}
zoom={4}
maxZoom={18}
style={{ height: '90vh', width: '100%' }} // Inline style for quick demo
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
/>
<MarkerClusterGroup chunkedLoading>
{markers.map((marker) => (
<Marker key={marker.id} position={marker.position}>
<Popup>{marker.name}</Popup>
</Marker>
))}
</MarkerClusterGroup>
</MapContainer>
);
}
export default MyMapComponent;