Skip to content

Commit dc2646c

Browse files
authored
Add prop to improve performance of MapView (47) (#801)
* Set `tracksViewChanges` prop automatically * Move out of delayed region and add to useEffect * Refactor tracksViewChanges and allow disable using prop * Update snapshots
1 parent 34a56e8 commit dc2646c

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

packages/maps/src/__tests__/MapView.test.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ describe("MapView tests", () => {
186186
}
187187
}
188188
onPress={[Function]}
189+
tracksViewChanges={true}
189190
/>,
190191
<Marker
191192
coordinate={
@@ -195,6 +196,7 @@ describe("MapView tests", () => {
195196
}
196197
}
197198
onPress={[Function]}
199+
tracksViewChanges={true}
198200
/>,
199201
],
200202
[
@@ -206,6 +208,7 @@ describe("MapView tests", () => {
206208
}
207209
}
208210
onPress={[Function]}
211+
tracksViewChanges={true}
209212
/>,
210213
<Marker
211214
coordinate={
@@ -215,6 +218,7 @@ describe("MapView tests", () => {
215218
}
216219
}
217220
onPress={[Function]}
221+
tracksViewChanges={true}
218222
/>,
219223
],
220224
]
@@ -247,6 +251,7 @@ describe("MapView tests", () => {
247251
}
248252
}
249253
onPress={[Function]}
254+
tracksViewChanges={true}
250255
/>,
251256
<Marker
252257
coordinate={
@@ -256,6 +261,7 @@ describe("MapView tests", () => {
256261
}
257262
}
258263
onPress={[Function]}
264+
tracksViewChanges={true}
259265
/>,
260266
],
261267
[
@@ -267,6 +273,7 @@ describe("MapView tests", () => {
267273
}
268274
}
269275
onPress={[Function]}
276+
tracksViewChanges={true}
270277
/>,
271278
<Marker
272279
coordinate={
@@ -276,6 +283,7 @@ describe("MapView tests", () => {
276283
}
277284
}
278285
onPress={[Function]}
286+
tracksViewChanges={true}
279287
/>,
280288
],
281289
]
@@ -332,6 +340,7 @@ describe("MapView tests", () => {
332340
}
333341
}
334342
onPress={[Function]}
343+
tracksViewChanges={true}
335344
/>,
336345
<Marker
337346
coordinate={
@@ -341,6 +350,7 @@ describe("MapView tests", () => {
341350
}
342351
}
343352
onPress={[Function]}
353+
tracksViewChanges={true}
344354
/>,
345355
],
346356
]

packages/maps/src/components/MapView.tsx

+32-2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ export interface MapViewProps<T>
4242
longitude?: number;
4343
autoClusterMarkers?: boolean;
4444
autoClusterMarkersDistanceMeters?: number;
45+
// Improves performance when panning by temporarily preventing markers from tracking view changes
46+
// See `tracksViewChanges`: https://github.com/react-native-maps/react-native-maps/blob/master/docs/marker.md#props
47+
disableTrackViewChangesWhenPanning?: boolean;
4548
markersData?: T[];
4649
keyExtractor?: (item: T, index: number) => string;
4750
renderItem?: ({ item, index }: { item: T; index: number }) => JSX.Element;
@@ -59,6 +62,7 @@ const MapViewF = <T extends object>({
5962
loadingEnabled = true,
6063
autoClusterMarkers = false,
6164
autoClusterMarkersDistanceMeters = 1000,
65+
disableTrackViewChangesWhenPanning = true,
6266
markersData,
6367
keyExtractor,
6468
renderItem,
@@ -73,6 +77,8 @@ const MapViewF = <T extends object>({
7377
animateToLocation: (location: ZoomLocation) => void;
7478
mapRef: React.RefObject<MapViewComponent>;
7579
}) => {
80+
const [markerTracksViewChanges, setMarkerTracksViewChanges] =
81+
React.useState(true);
7682
const [currentRegion, setCurrentRegion] = React.useState<Region | null>(null);
7783
const delayedRegionValue = useDebounce(currentRegion, 300);
7884

@@ -235,6 +241,7 @@ const MapViewF = <T extends object>({
235241
};
236242

237243
callOnRegionChange();
244+
238245
// onRegionChange excluded to prevent calling on every rerender when using an anonymous function (which is most common)
239246
// eslint-disable-next-line react-hooks/exhaustive-deps
240247
}, [delayedRegionValue]);
@@ -283,6 +290,16 @@ const MapViewF = <T extends object>({
283290
initialCamera={camera}
284291
loadingEnabled={loadingEnabled}
285292
onRegionChange={setCurrentRegion}
293+
onTouchStart={() => {
294+
if (disableTrackViewChangesWhenPanning) {
295+
setMarkerTracksViewChanges(false);
296+
}
297+
}}
298+
onTouchEnd={() => {
299+
if (disableTrackViewChangesWhenPanning) {
300+
setMarkerTracksViewChanges(true);
301+
}
302+
}}
286303
onPress={(event) => {
287304
const coordinate = event.nativeEvent.coordinate;
288305
onPress?.(coordinate.latitude, coordinate.longitude);
@@ -292,7 +309,12 @@ const MapViewF = <T extends object>({
292309
>
293310
{markers.map((marker, index) =>
294311
renderMarker(
295-
marker.props,
312+
{
313+
...marker.props,
314+
tracksViewChanges: disableTrackViewChangesWhenPanning
315+
? markerTracksViewChanges
316+
: undefined,
317+
},
296318
index,
297319
getMarkerRef(getMarkerIdentifier(marker.props)),
298320
() => dismissAllOtherCallouts(getMarkerIdentifier(marker.props))
@@ -311,7 +333,13 @@ const MapViewF = <T extends object>({
311333
}}
312334
>
313335
{clusters.map((cluster, index) => (
314-
<React.Fragment key={index}>{cluster}</React.Fragment>
336+
<React.Fragment key={index}>
337+
{React.cloneElement(cluster, {
338+
tracksViewChanges: disableTrackViewChangesWhenPanning
339+
? markerTracksViewChanges
340+
: undefined,
341+
})}
342+
</React.Fragment>
315343
))}
316344
</MapMarkerContext.Provider>
317345

@@ -338,6 +366,8 @@ const MapViewF = <T extends object>({
338366
showsCompass,
339367
style,
340368
zoom,
369+
markerTracksViewChanges,
370+
disableTrackViewChangesWhenPanning,
341371
]
342372
);
343373

packages/maps/src/components/marker-cluster/MapMarkerCluster.tsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@ import { MapViewContext } from "../MapViewCommon";
99
import { flattenReactFragments } from "@draftbit/ui";
1010
import { MapMarkerContext } from "../MapView";
1111

12+
interface MapMarkerClusterProps {
13+
tracksViewChanges?: boolean;
14+
}
15+
1216
/**
1317
* Component that clusters all markers provided in as children to a single point when zoomed out, and shows the markers themselves when zoomed in
1418
* Renders a default component that shows the number of components inside cluster
1519
*
1620
* Also accepts MapMarkerClusterView to override the rendered cluster component
1721
*/
18-
const MapMarkerCluster: React.FC<React.PropsWithChildren> = ({
19-
children: childrenProp,
20-
}) => {
22+
const MapMarkerCluster: React.FC<
23+
React.PropsWithChildren<MapMarkerClusterProps>
24+
> = ({ children: childrenProp, tracksViewChanges }) => {
2125
const { region, animateToLocation } = React.useContext(MapViewContext);
2226

2327
const children = React.useMemo(
@@ -75,14 +79,18 @@ const MapMarkerCluster: React.FC<React.PropsWithChildren> = ({
7579
longitude,
7680
children: clusterView,
7781
onPress,
82+
tracksViewChanges,
7883
})}
7984
</MapMarkerClusterContext.Provider>
8085
);
8186
}}
8287
>
8388
{markers.map((marker, index) =>
84-
renderMarker(marker.props, index, getMarkerRef(marker.props), () =>
85-
onMarkerPress(marker.props)
89+
renderMarker(
90+
{ ...marker.props, tracksViewChanges },
91+
index,
92+
getMarkerRef(marker.props),
93+
() => onMarkerPress(marker.props)
8694
)
8795
)}
8896
</MarkerClusterer>

0 commit comments

Comments
 (0)