Skip to content
Sandny Blog
  • Home
  • Java
  • JavaScript
  • AWS
  • Embedded
  • About
how to optimize react-native map view JavaScript

How to optimize react-native map views

  • June 26, 2021June 27, 2021
  • by Coder Kai

React native always has been quite painful when it comes to performance compared to a native application. Today we will focus on increasing the performance and how to optimize react-native map view which has many pegs or markers.

For this example, we use a cluster of markers that change with the region.

First we will check for a library to render react-native map view. https://github.com/react-native-maps/react-native-maps this is the most commonly used map view that used to render most of the maps.

You can install the map view using this link https://github.com/react-native-maps/react-native-maps/blob/master/docs/installation.md It has some tricky parts and if you face any problems when integrating, leave a comment and I will help you out.

In the following link, this full exercise is explained including the installation. Please refer if you need more elaborative.


How to optimize react native map view

Steps involving optimizing

  1. Add markers to the map in google map view.
  2. Involve state update in markers and the list when region changes.
  3. Avoid track view changes after the state is updated.
  4. Debounce region change calls for time or radius.

With the above steps, you can optimize react-native map view whenever you have a state update on markers or region.

1. Add markers to the map in google map view

If you render the iOS map viwe you can see its performance is better when loading a large number of markers. But when we turn into google maps it is not very optimized and we have to take extra measures to optimize it.

how to optimize react-native map view

Initial marker view when map is mounted.

The following code will load the markers to the map view. It will load a random number of makers to the app map view.

import React, {useState, useEffect, useCallback} from 'react';
import randomLocation from 'random-location';
import {debounce} from 'lodash';
import {View, StyleSheet, Dimensions} from 'react-native';
import MapView, {Marker, PROVIDER_GOOGLE} from 'react-native-maps';

const INTIAL_REGION = {   
    latitude: 37.7768006,
    longitude: -122.4187928,
};
const LocationView = () => {
  const [markers, setMarkers] = useState([]);
  const [region, setRegion] = useState(INTIAL_REGION);

  const onChangeLocation = useCallback(debounce((region) => {
    console.log('debounced region', region);
    const locations = new Array(100).fill(undefined).map(() => {
      const R = 4000; // meters

      const randomPoint = randomLocation.randomCirclePoint(region, R);
      return randomPoint;
    });

    setMarkers(locations);
  }, 1000, {trailing: true, leading: false}), []);


  useEffect(() => {
    onChangeLocation(region);
  }, [region]);

  // extra code to demonstrate what we will do
  const onRegionChange = newRegion => {
    setRegion(newRegion);
  };

  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        provider={PROVIDER_GOOGLE}
        onRegionChange={onRegionChange}
        initialRegion={{
          ...INTIAL_REGION,
          latitudeDelta: 0.1922,
          longitudeDelta: 0.0421,
        }}>
        {markers.map((point, index) => (
          <ImageMarker key={index} point={point} />
        ))}
      </MapView>
    </View>
  );
};

const ImageMarker = ({point}) => {
  const [shouldTrack, setTrack] = useState(false);
  const [image, setImage] = useState('https://via.placeholder.com/50/0000FF');

  useEffect(() => {
    setTrack(true);
    setImage('https://via.placeholder.com/50/0000FF');
    // Could be a network call to fetch some data or animation which update the state
    const timeout = setTimeout(() => {
      setImage('https://via.placeholder.com/50');
      setTrack(false);
    }, 600);
    return () => clearInterval(timeout);
  }, [point]);

  return (
    <Marker tracksViewChanges={shouldTrack} coordinate={point} image={{uri: image}} />
  );
};

2. Involve state update in markers and the list when region changes.

const ImageMarker = ({point}) => {
  const [shouldTrack, setTrack] = useState(false);
  const [image, setImage] = useState('https://via.placeholder.com/50/0000FF');

  useEffect(() => {
    setTrack(true);
    setImage('https://via.placeholder.com/50/0000FF');
    // Could be a network call to fetch some data or animation which update the state
    const timeout = setTimeout(() => {
      setImage('https://via.placeholder.com/50');
      setTrack(false);
    }, 600);
    return () => clearInterval(timeout);
  }, [point]);

  return (
    <Marker tracksViewChanges={shouldTrack} coordinate={point} image={{uri: image}} />
  );
};

In the above code, we initially display a marker in blue and make it white after 600 milliseconds to demonstrate a state update.

3. Avoid track view changes after the state is updated

The following will increase the performance by about 50%. The marker should be passed with tracksViewChanges={false} once the state update is over.

For that, we can keep a state variable that needs to be toggled for state updates.

const ImageMarker = ({point}) => {
  const [shouldTrack, setTrack] = useState(false);

  useEffect(() => {
    setTrack(true);
    setImage('https://via.placeholder.com/50/0000FF');
    // simulate the network call and the state update
    const timeout = setTimeout(() => {
      setImage('https://via.placeholder.com/50');
      setTrack(false);
    }, 600);
    return () => clearInterval(timeout);
  }, [point]);

  // tracksViewChanges should be false when state update is over
  return (
    <Marker tracksViewChanges={shouldTrack} coordinate={point} image={{uri: image}} />
  );
};

4. Debounce region change calls for time or radius.

By using Lodash debounce we can avoid constant updates of the UI for the region change.

  const onChangeLocation = useCallback(debounce((region) => {
    console.log('debounced region', region);
    const locations = new Array(100).fill(undefined).map(() => {
      const R = 4000; // meters

      const randomPoint = randomLocation.randomCirclePoint(region, R);
      return randomPoint;
    });

    setMarkers(locations);
  }, 1000, {trailing: true, leading: false}), []);

}, 1000, {trailing: true, leading: false}), []);

Here 1000 means it will wait for 1000 milliseconds before executing the callback function. trailing and leading are the configurations for the debounce function. useCallbackwill make sure it will be initialized once per the component initiation.

If you have any issues with the implementation, please leave a comment to help others as well. Happy Coding!

Avoid multiple clicks using debounce with react hooks
How to use Typescript with arrays
Coder Kai
A humble developer
android google maps ios mobile react react-native

Related articles

Multiple refs for an array of React Elements
Using multiple refs for an…
Immutable and Mutable Values in Javascript
07. Immutable and Mutable Values…
wrapper objects in javascript
06. Wrapper objects in Javascript
globals undefined and null values in javascript
05 Global, null and undefined…
Javascript Booleans and Equality
04. Javascript Guide Booleans and…
How to add Chakra UI Animations
Chakra UI Animations
SSL Websocket using Nginx Proxy
SSL Websocket proxy with Nginx…
Change python version correctly
Python is not setting correct…
optimize React.js load time
How to optimize React.js app…
Multiple refs for an array of React Elements
How to use IntersectionObserver to…
Multiple refs for an array of React Elements
How to dismiss dropdowns when…
Javascript guide Strings
03. Javascript Guide – Strings
How to fetch data with useEffect
How to fetch data with…
add styles to stripe elements
How to add styles to…
Typescript
How to use Typescript with…
debounce with react hooks
Avoid multiple clicks using debounce…
Numbers inJavascript
02. Javascript Guide – Numbers
Introduction to Javascript
01. Javascript Guide – Introduction…
Nginx Load Balancer with docker…
Create React App Using npx

Categories

  • android 3
  • Apollo Client 1
  • AWS 8
    • AppSync 5
    • EC2 1
    • EKS 1
    • Route53 1
    • S3 1
  • AWS Amplify 1
  • Chakra UI 1
  • Docker 1
  • Embedded 1
  • EmberJS 1
  • FCM 1
  • Godaddy 1
  • GraphQL 3
  • ios 1
  • Jasper 1
  • Java 10
    • Java 11 1
    • Java 14 1
  • JavaEE 2
  • JavaScript 39
    • Express.js 4
    • Javascript Guide 7
    • Node.js 3
    • react-native 4
    • React.js 17
    • Typescript 1
  • Kubernetes 1
  • machine learning 1
  • Maven 2
  • OCaml 3
  • PostgreSQL 1
  • Python 2
  • react-native 4
  • ReactJS 3
  • sass 1
  • Server 6
  • spark 1
  • Terraform 2
  • Ubuntu 4
  • Uncategorized 1
  • webpack 2

Recent Comments

  • binance Registrera dig on Higher order component wrappers using React.js and reusable components.
  • kopya site buyhacklink.com on How to create Lambda function with Terraform
  • Pamela587 on Chakra UI Animations

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Archives

  • October 2022 3
  • September 2022 7
  • May 2022 1
  • December 2021 1
  • August 2021 1
  • July 2021 6
  • June 2021 3
  • February 2021 1
  • July 2020 1
  • December 2019 5
  • November 2019 6
  • October 2019 3
  • August 2019 1
  • March 2019 1
  • February 2019 1
  • January 2019 2
  • December 2018 1
  • September 2018 2
  • August 2018 1
  • June 2018 1
  • February 2018 1
  • November 2017 2
  • October 2017 5
  • September 2017 1
  • June 2017 1
  • May 2017 10
Sandny Blog space
Theme by Colorlib Powered by WordPress