import { useEffect, useMemo, useReducer } from "react" import Supercluster, {type ClusterProperties } from "supercluster" import { useMapViewport } from "./use-map-viewport" import type { FeatureCollection, GeoJsonProperties, Point } from "geojson" export function useSupercluster( geojson: FeatureCollection, superclusterOptions: Supercluster.Options ) { // create the clusterer and keep it const clusterer = useMemo(() => { return new Supercluster(superclusterOptions) }, [superclusterOptions]) // version-number for the data loaded into the clusterer // (this is needed to trigger updating the clusters when data was changed) const [version, dataWasUpdated] = useReducer((x: number) => x + 1, 0) // when data changes, load it into the clusterer useEffect(() => { clusterer.load(geojson.features) dataWasUpdated() }, [clusterer, geojson]) // get bounding-box and zoomlevel from the map const { bbox, zoom } = useMapViewport({ padding: 100 }) // retrieve the clusters within the current viewport const clusters = useMemo(() => { // don't try to read clusters before data was loaded into the clusterer (version===0), // otherwise getClusters will crash if (!clusterer || version === 0) return [] return clusterer.getClusters(bbox, zoom) }, [version, clusterer, bbox, zoom]) return { clusters, } }