@@ -12,7 +12,8 @@ import { MapViewContext, ZoomLocation } from "./MapViewCommon";
1212import { MapMarkerClusterView } from "./marker-cluster" ;
1313import { flattenReactFragments } from "@draftbit/ui" ;
1414import type { MapMarker as MapMarkerRefType } from "react-native-maps" ;
15- import { useDeepCompareMemo } from "./useDeepCompareMemo" ;
15+ import { useDeepCompareMemo , useDebounce } from "../utils" ;
16+ import MapCircle from "./MapCircle" ;
1617
1718export interface MapMarkerContextType {
1819 onMarkerPress : ( marker : MapMarkerProps ) => void ;
@@ -26,8 +27,15 @@ export const MapMarkerContext = React.createContext<MapMarkerContextType>({
2627 getMarkerRef : ( ) => undefined ,
2728} ) ;
2829
30+ interface RegionWithZoom extends Region {
31+ zoom : number ;
32+ }
33+
2934export interface MapViewProps < T >
30- extends Omit < MapViewComponentProps , "onRegionChangeComplete" | "onPress" > {
35+ extends Omit <
36+ MapViewComponentProps ,
37+ "onRegionChangeComplete" | "onPress" | "onRegionChange"
38+ > {
3139 apiKey : string ;
3240 zoom ?: number ;
3341 latitude ?: number ;
@@ -37,7 +45,7 @@ export interface MapViewProps<T>
3745 markersData ?: T [ ] ;
3846 keyExtractor ?: ( item : T , index : number ) => string ;
3947 renderItem ?: ( { item, index } : { item : T ; index : number } ) => JSX . Element ;
40- onRegionChange ?: ( region : Region ) => void ;
48+ onRegionChange ?: ( region : RegionWithZoom ) => void ;
4149 onPress ?: ( latitude : number , longitude : number ) => void ;
4250}
4351
@@ -66,6 +74,7 @@ const MapViewF = <T extends object>({
6674 mapRef : React . RefObject < MapViewComponent > ;
6775} ) => {
6876 const [ currentRegion , setCurrentRegion ] = React . useState < Region | null > ( null ) ;
77+ const delayedRegionValue = useDebounce ( currentRegion , 300 ) ;
6978
7079 const markerRefs = React . useMemo <
7180 Map < string , React . RefObject < MapMarkerRefType > >
@@ -216,10 +225,28 @@ const MapViewF = <T extends object>({
216225 }
217226 } , [ latitude , longitude , zoom , animateToLocation ] ) ;
218227
228+ // Use delayed/debounced value to prevent too many calls when map is being dragged
229+ React . useEffect ( ( ) => {
230+ const callOnRegionChange = async ( ) => {
231+ if ( delayedRegionValue ) {
232+ const camera = await mapRef . current ?. getCamera ( ) ;
233+ onRegionChange ?.( { ...delayedRegionValue , zoom : camera ?. zoom ?? 1 } ) ;
234+ }
235+ } ;
236+
237+ callOnRegionChange ( ) ;
238+ // onRegionChange excluded to prevent calling on every rerender when using an anonymous function (which is most common)
239+ // eslint-disable-next-line react-hooks/exhaustive-deps
240+ } , [ delayedRegionValue ] ) ;
241+
219242 const markers = React . useMemo (
220243 ( ) => getChildrenForType ( MapMarker ) ,
221244 [ getChildrenForType ]
222245 ) ;
246+ const circles = React . useMemo (
247+ ( ) => getChildrenForType ( MapCircle ) ,
248+ [ getChildrenForType ]
249+ ) ;
223250 const clusters = React . useMemo (
224251 ( ) => getChildrenForType ( MapMarkerCluster ) ,
225252 [ getChildrenForType ]
@@ -255,9 +282,6 @@ const MapViewF = <T extends object>({
255282 showsCompass = { showsCompass }
256283 initialCamera = { camera }
257284 loadingEnabled = { loadingEnabled }
258- onRegionChangeComplete = { ( region ) => {
259- onRegionChange ?.( region ) ;
260- } }
261285 onRegionChange = { setCurrentRegion }
262286 onPress = { ( event ) => {
263287 const coordinate = event . nativeEvent . coordinate ;
@@ -290,6 +314,8 @@ const MapViewF = <T extends object>({
290314 < React . Fragment key = { index } > { cluster } </ React . Fragment >
291315 ) ) }
292316 </ MapMarkerContext . Provider >
317+
318+ { circles }
293319 </ MapViewComponent >
294320 ) ,
295321 [
@@ -337,8 +363,8 @@ class MapView<T extends object> extends React.Component<
337363 heading : 0 ,
338364 pitch : 0 ,
339365 center : {
340- latitude,
341- longitude,
366+ latitude : Number ( latitude ) ,
367+ longitude : Number ( longitude ) ,
342368 } ,
343369 } ;
344370
0 commit comments