Introduction to react-native-maps
Tags: react, reactnative
Published: 2020-05-06 15:18:40

---
title: Introduction to react-native-maps
published: true
date: 2020-04-10 13:00:33 UTC
tags: react,react native
canonical_url: https://blog.logrocket.com/introduction-to-react-native-maps/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/2a7x7pcqy4ededo9sueg.png
---
**Written by [Gaurav Singhal](https://blog.logrocket.com/author/gauravsinghal/)**✏️

Having accurate information about your users’ location is a great way to enhance the user experience. For example, you could use this data to show users what is around them, offer exclusive deals for products and services in their area, and much more. Fortunately, if you have a React application, implementing maps is a breeze using the `react-native-maps` library.

`react-native-maps` is a component system for maps that ships with platform-native code that needs to be compiled together with React Native. In this guide, we’ll demonstrate how to integrate Google Maps into your React Native application and introduce you to fundamental components such as `<MapView />` and `<Marker>`.

Let’s get started!

## Installation

The first thing you need to do is [obtain the API key](https://developers.google.com/maps/documentation/android-sdk/get-api-key) for configuring Google Maps on Android. Once you have the API key, include it in your `AndroidManifest.xml` file as the child of the `<application>` element.

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

Next, run the following command to install `react-native-maps` in your project.

```jsx
yarn add react-native-maps -E
```

## Basic use

Remove all the default code from the `App.js` file and import the `<MapView />` component from `react-native-maps`.

```jsx
import MapView from "react-native-maps";
```

Inside the component, render the `<MapView />` component.

```jsx
import React from "react";

import MapView from "react-native-maps";

const App = () => {
  return (
    <MapView
      style={{ flex: 1 }}
      initialRegion={{
        latitude: 37.78825,
        longitude: -122.4324,
        latitudeDelta: 0.05,
        longitudeDelta: 0.05
      }}
    />
  );
};

export default App;
```

The `initialRegion` prop shows the region that is to be displayed on the map when the component mounts. The `initialRegion` value cannot be changed after it has been initialized. Don’t forget to add the style property to specify the dimensions. Otherwise, you’ll end up with a white screen. The value `{ flex: 1 }` will ensure that the [`<MapView />`](https://github.com/react-native-community/react-native-maps/blob/master/docs/mapview.md) takes up the entire screen.

You’ll need to pass an object with the latitude, longitude, and delta values of a region to the `initialRegion` prop. The `latitudeDelta` and `longitudeDelta` properties specify how much the area on the map must be zoomed. To change the region, use the `region` prop.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## Using `react-native-maps` with the `useState` hook

To change the region with the state hook, use the `onRegionChangeComplete` prop to set the new region into the state. The `onRegionChangeComplete` is a callback prop that is called only once when the region changes.

```jsx
import React, { useState } from "react";

import MapView from "react-native-maps";

const App = () => {
  const [region, setRegion] = useState({
    latitude: 51.5079145,
    longitude: -0.0899163,
    latitudeDelta: 0.01,
    longitudeDelta: 0.01
  });

  return (
    <MapView
      style={{ flex: 1 }}
      region={region}
      onRegionChangeComplete={region => setRegion(region)}
    />
  );
};

export default App;
```

## Displaying markers on the map

Start by importing `Marker` from `react-native-maps`.

```jsx
import MapView, { Marker } from "react-native-maps";
```

Next, render the `<Marker />` component as a child of `<MapView />`. Pass the coordinate for the marker in the `coordinate` prop.

```jsx
import React, { useState } from "react";

import MapView, { Marker } from "react-native-maps";

const App = () => {
  const [region, setRegion] = useState({
    latitude: 51.5078788,
    longitude: -0.0877321,
    latitudeDelta: 0.009,
    longitudeDelta: 0.009
  });

  return (
    <MapView
      style={{ flex: 1 }}
      region={region}
      onRegionChangeComplete={region => setRegion(region)}
    >
      <Marker coordinate={{ latitude: 51.5078788, longitude: -0.0877321 }} />
    </MapView>
  );
};

export default App;
```

The marker should be visible, as shown below.

![Marker on a Map](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/marker-on-map.jpeg?resize=311%2C640&ssl=1)

You can add `n` number of markers to the map and pass it as a direct child to the `<MapView />` component.

### Custom marker color

To change the color of the marker, use the `pinColor` prop.

```jsx
<Marker
  coordinate={{ latitude: 52.5200066, longitude: 13.404954 }}
  pinColor="green"
/>
```

### Custom marker image

You can also add a custom marker image by passing the `image` prop to the `<Marker />` component.

```jsx
<Marker
  coordinate={{ latitude: 52.5200066, longitude: 13.404954 }}
  image={require("./car.png")}
/>
```

### Custom marker view

The following will display a location with a custom marker view component.

```jsx
import React, { useState } from "react";
import { View, Text } from "react-native";

import MapView, { Marker } from "react-native-maps";

const CustomMarker = () => (
  <View
    style={{
      paddingVertical: 10,
      paddingHorizontal: 30,
      backgroundColor: "#007bff",
      borderColor: "#eee",
      borderRadius: 5,
      elevation: 10
    }}
  >
    <Text style={{ color: "#fff" }}>Berlin</Text>
  </View>
);

const App = () => {
  const [region, setRegion] = useState({
    latitude: 52.5200066,
    longitude: 13.404954,
    latitudeDelta: 0.005,
    longitudeDelta: 0.005
  });

  return (
    <MapView
      style={{ flex: 1 }}
      region={region}
      onRegionChangeComplete={region => setRegion(region)}
    >
      <Marker coordinate={{ latitude: 52.5200066, longitude: 13.404954 }}>
        <CustomMarker />
      </Marker>
    </MapView>
  );
};

export default App;
```

## Styling the map

Generate the JSON object you’ll use to design the map from the [Google style generator](https://mapstyle.withgoogle.com/).

Next, pass the generated style object to the `customMapStyle` prop of the `<MapView />` component.

```jsx
import React, { useState } from "react";
import { View, Text } from "react-native";

import MapView, { Marker } from "react-native-maps";

const mapStyle = [
  {
    elementType: "geometry",
    stylers: [
      {
        color: "#1d2c4d"
      }
    ]
  },
  {
    elementType: "labels.text.fill",
    stylers: [
      {
        color: "#8ec3b9"
      }
    ]
  },
  // ...
  {
    featureType: "water",
    elementType: "geometry.fill",
    stylers: [
      {
        color: "#3e73fd"
      }
    ]
  },
  {
    featureType: "water",
    elementType: "labels.text.fill",
    stylers: [
      {
        color: "#4e6d70"
      }
    ]
  }
];

const CustomMarker = () => (
  <View
    style={{
      paddingVertical: 10,
      paddingHorizontal: 30,
      backgroundColor: "#fff",
      borderColor: "#eee",
      borderRadius: 5,
      elevation: 10
    }}
  >
    <Text>Berlin</Text>
  </View>
);

const App = () => {
  const [region, setRegion] = useState({
    latitude: 52.5200066,
    longitude: 13.404954,
    latitudeDelta: 0.005,
    longitudeDelta: 0.005
  });

  return (
    <MapView
      style={{ flex: 1 }}
      region={region}
      onRegionChangeComplete={region => setRegion(region)}
      customMapStyle={mapStyle}
    >
      <Marker coordinate={{ latitude: 52.5200066, longitude: 13.404954 }}>
        <CustomMarker />
      </Marker>
    </MapView>
  );
};

export default App;
```

You can ignore the `mapStyle` variable. Since it will be generated from the map style generator, you only need to paste the JSON object into your code and send it to the `<MapView />` component.

![Custom-Styled Map](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/custom-styled-map.jpeg?resize=311%2C640&ssl=1)

As you can see, the map style changed from the default light theme to a customized dark theme.

## Animating to a coordinate

What if you want to animate to a particular coordinate?

First, create a ref to `<MapView />` using the `useRef()` hook.

```jsx
import React, { useState, useRef, useEffect } from "react";
import { View, Text } from "react-native";

import MapView, { Marker } from "react-native-maps";

// ...

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

  useEffect(() => {
    // ...
  }, []);

  return (
    <>
      <MapView
        style={{ flex: 1 }}
        ref={_map}
        initialRegion={{
          latitude: 52.5200066,
          longitude: 13.404954,
          latitudeDelta: 0.1,
          longitudeDelta: 0.1
        }}
      >
        <Marker coordinate={{ latitude: 52.5200066, longitude: 13.404954 }}>
          <CustomMarker />
        </Marker>
      </MapView>
    </>
  );
};

export default App;
```

Next, inside the `useEffect()` hook, use the `animateCamera()` function to animate the `MapView` region.

```jsx
useEffect(() => {
  if(_map.current) {
    _map.current.animateCamera(
      {
        center: {
          latitude: 50.1109221,
          longitude: 8.6821267
        }
        zoom: 15
      },
      5000
    );
  }
}, []);
```

The `useRef()` hook returns a mutable ref object whose `current` property has the value of the passed argument. If the value of `current` property is `undefined`, that means the component is not yet mounted. Now you can access any of the `<MapView />` methods using `_map.current`.

The `animateCamera()` method accepts an object with `center`, `zoom`, `heading`, and `altitude` properties as its argument and the animation duration in milliseconds. You can pass the region’s latitude and longitude in the `center` property, but unlike the `initialRegion` prop, you cannot give the delta values. The `zoom` property specifies the extent to which the region needs to be zoomed.

## Adding a line to the map

You can use the `<Polyline />` component from the `react-native-maps` library to create lines between multiple coordinates. It accepts an array of coordinates in its `coordinates` prop. You can also specify additional props for styling purposes, such as `strokeWidth`, `strokeColor`, etc.

Let’s create a path between Berlin and Frankfurt.

```jsx
import React from "react";
import MapView, { Polyline } from "react-native-maps";

const App = () => {
  const Berlin = {
    latitude: 52.5200066,
    longitude: 13.404954
  };

  const Frankfurt = {
    latitude: 50.1109221,
    longitude: 8.6821267
  };

  return (
    <>
      <MapView
        style={{ flex: 1 }}
        initialRegion={{
          latitude: 52.5200066,
          longitude: 13.404954,
          latitudeDelta: 0.1,
          longitudeDelta: 0.1
        }}
      >
        <Polyline coordinates={[Berlin, Franfurt]} />
      </MapView>
    </>
  );
};

export default App;
```

Store the coordinates for the locations in their respective variables and pass them in an array to the `coordinates` prop of the `<Polyline />` component.

If you look at the results, the line is drawn directly between these coordinates and does not take into account the actual geographical paths and roads. For that, you’ll need to establish multiple coordinates between the source and destination locations by using the Google Maps Direction API, which returns all possible routes between two places.

Create a `getDirections` function that accepts the coordinates in string format.

```jsx
const getDirections = async (startLoc, destinationLoc) => {
  try {
    const KEY = "YOUR GOOGLE API KEY";
    let resp = await fetch(
      `https://maps.googleapis.com/maps/api/directions/json?origin=${startLoc}&destination=${destinationLoc}&key=${KEY}`
    );
    let respJson = await resp.json();
    let points = decode(respJson.routes[0].overview_polyline.points);
    console.log(points);
    let coords = points.map((point, index) => {
      return {
        latitude: point[0],
        longitude: point[1]
      };
    });
    return coords;
  } catch (error) {
    return error;
  }
};
```

Import the `decode()` function from the `@mapbox/polyline` library.

```jsx
import { decode } from "@mapbox/polyline";
```

The `decode()` function will convert the encoded polyline points from the `overview_polyline.points` property into an array containing the latitude and longitude of all the coordinates.

```jsx
import React, { useState, useEffect } from "react";
import { View, Text } from "react-native";
import MapView, { Polyline } from "react-native-maps";
import { decode } from "@mapbox/polyline";

const getDirections = async (startLoc, destinationLoc) => {
  try {
    const KEY = "YOUR GOOGLE API KEY";
    let resp = await fetch(
      `https://maps.googleapis.com/maps/api/directions/json?origin=${startLoc}&destination=${destinationLoc}&key=${KEY}`
    );
    let respJson = await resp.json();
    let points = decode(respJson.routes[0].overview_polyline.points);
    let coords = points.map((point, index) => {
      return {
        latitude: point[0],
        longitude: point[1]
      };
    });
    return coords;
  } catch (error) {
    return error;
  }
};

const App = () => {
  const [coords, setCoords] = useState([]);

  useEffect(() => {
    getDirections("52.5200066,13.404954", "50.1109221,8.6821267")
      .then(coords => setCoords(coords))
      .catch(err => console.log("Something went wrong"));
  }, []);

  return (
    <>
      <MapView
        style={{ flex: 1 }}
        initialRegion={{
          latitude: 52.5200066,
          longitude: 13.404954,
          latitudeDelta: 0.1,
          longitudeDelta: 0.1
        }}
      >
        {coords.length > 0 && <Polyline coordinates={coords} />}
      </MapView>
    </>
  );
};

export default App;
```

## Conclusion

You should now have a basic understanding of how to implement maps, their benefits, and how to build features on top of the `react-native-maps` library. You can implement these lessons into your work to build myriad types of applications, from taxi services, to restaurant finders, to delivery apps, and much more. The `react-native-maps` library makes it simple to integrate maps and is an essential player in the React Native ecosystem.

* * * 
## Full visibility into production React apps 

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, [try LogRocket.](https://www2.logrocket.com/react-performance-monitoring)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/eq752g8qhbffxt3hp9t4.png)

[LogRocket](https://www2.logrocket.com/react-performance-monitoring) is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — [start monitoring for free.](https://www2.logrocket.com/react-performance-monitoring)
* * *

The post [Introduction to react-native-maps](https://blog.logrocket.com/introduction-to-react-native-maps/) appeared first on [LogRocket Blog](https://blog.logrocket.com).