Unlock the Power of Location-Based Features in Your React Native App

What is React Native Maps?

React Native Maps is a component system that ships with platform-native code, allowing you to compile it together with React Native. This library provides fundamental components like <MapView /> and <Marker> to help you create stunning map-based features.

Getting Started with React Native Maps

To get started, you’ll need to obtain an API key to incorporate Google Maps functionality into your app. Follow these steps to procure your API secrets:

Then, add the following code block to android/app/src/main/AndroidManifest.xml to connect your SDK key to the React Native project:

<meta-data
  android:name="com.google.android.geo.API_KEY"
  android:value="YOUR_API_KEY"/>

Next, install react-native-maps in your project using the following command:

npm install react-native-maps

Setting Up the Map Default View

Remove all default code from the App.js file and import the <MapView /> component from react-native-maps. Render the <MapView /> component and specify the initial region using the initialRegion prop. Don’t forget to add the style property to set the dimensions; otherwise, you’ll end up with a white screen.

import React from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Marker } from 'eact-native-maps';

const App = () => {
  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        initialRegion={{
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  map: {
    flex: 1,
  },
});

Using React Native Maps with the useState Hook

To change the region dynamically, use the onRegionChangeComplete prop to set the new region into the state. This callback prop runs when the user stops panning around the map.

import React, { useState } from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Marker } from 'eact-native-maps';

const App = () => {
  const [region, setRegion] = useState({
    latitude: 37.78825,
    longitude: -122.4324,
    latitudeDelta: 0.0922,
    longitudeDelta: 0.0421,
  });

  const handleRegionChangeComplete = (newRegion) => {
    setRegion(newRegion);
  };

  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        initialRegion={region}
        onRegionChangeComplete={handleRegionChangeComplete}
      />
    </View>
  );
};

Adding a Marker in React Native Maps

Import the Marker component from react-native-maps and render it as a child of <MapView />. Pass the coordinate for the marker in the coordinate prop. You can add multiple markers to the map and pass them as direct children to the <MapView /> component.

import React from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Marker } from 'eact-native-maps';

const App = () => {
  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        initialRegion={{
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      >
        <Marker
          coordinate={{
            latitude: 37.78825,
            longitude: -122.4324,
          }}
        />
      </MapView>
    </View>
  );
};

Customizing the Map Marker

Change the marker color using the pinColor prop or add a custom marker image by passing the image prop to the <Marker /> component. You can also use custom marker views to indicate locations using symbols.

import React from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Marker } from 'eact-native-maps';

const App = () => {
  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        initialRegion={{
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      >
        <Marker
          coordinate={{
            latitude: 37.78825,
            longitude: -122.4324,
          }}
          pinColor="blue"
          image={require('./custom-marker.png')}
        />
      </MapView>
    </View>
  );
};

Styling the Map

Generate a JSON object to design the map using the Google style generator. Then, pass the generated style object to the customMapStyle prop of the <MapView /> component. This will change the map style from the default light theme to a dark theme.

import React from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Marker } from 'eact-native-maps';

const App = () => {
  const mapStyle = [
    {
      elementType: 'geometry',
      stylers: [
        {
          color: '#242f3e',
        },
      ],
    },
    {
      elementType: 'labels.text.stroke',
      stylers: [
        {
          color: '#242f3e',
        },
      ],
    },
    {
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#746855',
        },
      ],
    },
    {
      featureType: 'administrative.locality',
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#d59563',
        },
      ],
    },
    {
      featureType: 'poi',
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#d59563',
        },
      ],
    },
    {
      featureType: 'poi.park',
      elementType: 'geometry',
      stylers: [
        {
          color: '#263c3f',
        },
      ],
    },
    {
      featureType: 'poi.park',
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#6b9a76',
        },
      ],
    },
    {
      featureType: 'road',
      elementType: 'geometry',
      stylers: [
        {
          color: '#38414e',
        },
      ],
    },
    {
      featureType: 'road',
      elementType: 'geometry.stroke',
      stylers: [
        {
          color: '#212a37',
        },
      ],
    },
    {
      featureType: 'road',
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#9ca5b3',
        },
      ],
    },
    {
      featureType: 'road.highway',
      elementType: 'geometry',
      stylers: [
        {
          color: '#746855',
        },
      ],
    },
    {
      featureType: 'road.highway',
      elementType: 'geometry.stroke',
      stylers: [
        {
          color: '#1f2835',
        },
      ],
    },
    {
      featureType: 'road.highway',
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#f3d19c',
        },
      ],
    },
    {
      featureType: 'transit',
      elementType: 'geometry',
      stylers: [
        {
          color: '#2f3948',
        },
      ],
    },
    {
      featureType: 'transit.station',
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#d59563',
        },
      ],
    },
    {
      featureType: 'water',
      elementType: 'geometry',
      stylers: [
        {
          color: '#17263c',
        },
      ],
    },
    {
      featureType: 'water',
      elementType: 'labels.text.fill',
      stylers: [
        {
          color: '#515c6d',
        },
      ],
    },
    {
      featureType: 'water',
      elementType: 'labels.text.stroke',
      stylers: [
        {
          color: '#17263c',
        },
      ],
    },
  ];

  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        initialRegion={{
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
        customMapStyle={mapStyle}
      />
    </View>
  );
};

Getting the Current Location or a Specific Coordinate

To animate to a particular coordinate, create a reference to <MapView /> using the useRef() Hook. Then, use the animateToRegion() method to control the MapView component.

import React, { useRef } from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Marker } from 'eact-native-maps';

const App = () => {
  const mapViewRef = useRef(null);

  const handlePress = () => {
    mapViewRef.current.animateToRegion({
      latitude: 37.78825,
      longitude: -122.4324,
      latitudeDelta: 0.0922,
      longitudeDelta: 0.0421,
    });
  };

  return (
    <View style={styles.container}>
      <MapView
        ref={mapViewRef}
        style={styles.map}
        initialRegion={{
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      />
      <Button title="Animate to coordinate" onPress={handlePress} />
    </View>
  );
};

Using <Polyline /> in React Native Maps

Create lines between multiple coordinates using the <Polyline /> component from react-native-maps. Pass an array of coordinates in the coordinates prop and specify additional props for styling purposes.

import React from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Polyline } from 'eact-native-maps';

const App = () => {
  const coordinates = [
    {
      latitude: 37.78825,
      longitude: -122.4324,
    },
    {
      latitude: 37.79625,
      longitude: -122.4424,
    },
    {
      latitude: 37.80425,
      longitude: -122.4524,
    },
  ];

  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        initialRegion={{
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      >
        <Polyline
          coordinates={coordinates}
          strokeColor="blue"
          strokeWidth={5}
        />
      </MapView>
    </View>
  );
};

Using the Google Maps Direction API

To draw lines that take into account actual geographical paths and roads, use the Google Maps Direction API. Enable the API for your project, then create a helper function to get directions. This will return all possible routes between two places.

import React, { useState, useEffect } from 'eact';
import { View, StyleSheet } from 'eact-native';
import MapView, { Polyline } from 'eact-native-maps';

const App = () => {
  const [directions, setDirections] = useState(null);

  useEffect(() => {
    const getDirections = async () => {
      const response = await fetch(
        `https://maps.googleapis.com/maps/api/directions/json?origin=37.78825,-122.4324&destination=37.79625,-122.4424&mode=driving&key=YOUR_API_KEY`
      );
      const data = await response.json();
      setDirections(data.routes[0].overview_polyline.points);
    };
    getDirections();
  }, []);

  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        initialRegion={{
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      >
        {directions && (
          <Polyline
            coordinates={decodePolyline(directions)}
            strokeColor="blue"
            strokeWidth={5}
          />
        )}
      </MapView>
    </View>
  );
};

const decodePolyline = (polylineString) => {
  const polylineArray = polylineString.split(',');
  const coordinates = [];
  for (let i = 0; i < polylineArray.length; i += 2) {
    coordinates.push({
      latitude: parseFloat(polylineArray[i]),
      longitude: parseFloat(polylineArray[i + 1]),
    });
  }
  return coordinates;
};

Leave a Reply