Skip to main content

MapView

The main export — a clustered MapView with the same API as react-native-map-clustering.

import MapView from 'react-native-better-clustering'
import { Marker } from 'react-native-maps'

react-native-better-clustering/compat is a backwards-compatible alias of the same component.

Basic usage​

<MapView
style={{ flex: 1 }}
initialRegion={{
latitude: 52.23,
longitude: 21.01,
latitudeDelta: 0.35,
longitudeDelta: 0.35,
}}
radius={56}
minPoints={2}
clusterColor="#FFCC00"
clusterTextColor="#000000"
>
{points.map((point) => (
<Marker
key={point.id}
coordinate={{
latitude: point.latitude,
longitude: point.longitude,
}}
/>
))}
</MapView>

Clustering props​

All standard react-native-maps MapView props are supported, plus:

PropDefaultDescription
radius~6% of screen widthCluster radius in pixels
minPoints2Minimum points to form a cluster
minZoom1Minimum zoom level
maxZoom20Maximum zoom level for clustering
extent512Tile extent (supercluster)
nodeSize64KD-tree leaf size
clusteringEnabledtrueToggle clustering
spiralEnabledtrueSpider layout at max zoom
spiderLineColor#FF0000Color of spider connector lines
clusterColor#0F52FFDefault cluster bubble color (GMI brand blue)
clusterTextColor#FFFFFFDefault cluster label color
clusterFontFamily—Font family for cluster count label
animationEnabledtrueAnimate cluster changes (iOS only)
layoutAnimationConf200ms easeInEaseOut create/delete + scale updateLayoutAnimation config when animationEnabled (tuned for cluster bubble transitions; pass a custom config to override)
clusterFadeInDuration250Cross-fade duration (ms) for default cluster bubbles on zoom: new bubbles fade in while removed ones linger and fade out, eliminating the blink from native annotations being added/removed (iOS + Android). Driven by Reanimated on the UI thread. The fade-out cross-fade is applied to the settled cluster set only — during an active pinch/pan, removed bubbles are dropped immediately so a continuous zoom does not stack multiple bubble generations and overload the JS thread. Gated by animationEnabled; ignored with a custom renderCluster. Set to 0 to disable
tracksViewChangesfalseForwarded to default cluster markers
edgePadding50px each sidePadding for fitToCoordinates on cluster press
preserveClusterPressBehaviorfalseSkip auto fitToCoordinates on cluster press
selectedClusterId—Highlight a cluster by id
selectedClusterColor#FF5722Color when cluster is selected
width / heightwindow sizeSeed map dimensions before onLayout
clusterUpdateIntervalMs100Minimum interval (ms) between cluster recomputations while the map is moving; 0 recomputes only on settle
superClusterRef—Ref to access the underlying Supercluster engine
mapRef—Callback ref to the inner react-native-maps instance

Callbacks​

PropSignatureDescription
onClusterPress(cluster, markers) => voidFired when a cluster is tapped
onMarkersChange(markers) => voidFired when visible markers/clusters change: once the first index has loaded, then only when the visible set changes. A re-render with the same marker coordinates does not fire it, so onMarkersChange={setState} is safe
onRegionChangeComplete(region, details, markers) => voidExtends the maps callback with current markers
onError(error) => voidFired when the native cluster index fails to build, for example because the app was not rebuilt after installing the library. Markers from an earlier successful build keep showing. Without it, the error is thrown during render so an error boundary (and LogBox in development) shows it — see Troubleshooting

Per-marker opt-out​

Markers cluster by default (cluster omitted or cluster={true}). Exclude individual markers from clustering:

<Marker
cluster={false}
coordinate={{ latitude: 52.23, longitude: 21.01 }}
/>

Custom cluster UI​

Pass renderCluster for full control over the cluster bubble:

import MapView, {
type RenderClusterProps,
} from 'react-native-better-clustering'
import { Marker } from 'react-native-maps'

const renderCluster = (cluster: RenderClusterProps) => {
const [longitude, latitude] = cluster.geometry.coordinates

return (
<Marker
coordinate={{ latitude, longitude }}
onPress={cluster.onPress}
tracksViewChanges={cluster.tracksViewChanges}
>
{/* your cluster bubble */}
</Marker>
)
}

<MapView renderCluster={renderCluster} {...props}>
{/* markers */}
</MapView>

Cluster features include properties.point_count, properties.point_count_abbreviated, and properties.getExpansionRegion() for zoom-on-tap.

Types​

import type {
ClusteredMapViewProps,
RenderClusterProps,
} from 'react-native-better-clustering'

ClusteredMapViewProps is the full props type for the clustered MapView.