← Back to list

Exploring Mapbox in React Native

A simple guide to adding maps, markers, routes, and location features

Mahisa Ajy Kusuma · 2025-11-10 03:49 · 63 claps · 6.4 min read
#mapbox #react-native
Open on Medium ↗
Wiki topics: 🌐 · Web Development 📱 · Mobile Development

Exploring Mapbox in React Native

A simple guide to adding maps, markers, routes, and location features

After setting up Mapbox in React Native for Android and iOS in the previous articles, it’s time to explore how to actually use it in your app.

In this post, we’ll walk through several essential Mapbox features you can implement with just a few lines of code:

  • Adding a Marker
  • Customizing the Default Marker
  • Replacing a Marker with an Image
  • Changing the Map Style (e.g., Dark Mode)
  • Getting the Current Location
  • Displaying Multiple Markers
  • Creating a Custom Callout
  • Drawing a Polyline (Route)

Let’s dive in

Adding a Marker

This is the simplest way to display a map and place a single marker at a specific coordinate.

import React from 'react';
import { StyleSheet, View } from 'react-native';
import Mapbox, { MapView, Camera, PointAnnotation } from '@rnmapbox/maps';

export default function AddMarker() {
  return (
    <View style={styles.container}>
      <MapView style={styles.map}>
        <Camera
          zoomLevel={14}
          centerCoordinate={[106.8272, -6.1754]}
        />
        <PointAnnotation id="marker1" coordinate={[106.8272, -6.1754]} />
      </MapView>
    </View>
  );
}

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

Customizing the map marker

By default, Mapbox shows a red pin as your marker. But you can easily customize it — change its color, turn it into a circle, or even replace it with your own image to better match your app’s design.

Changing the color

import React from 'react';
import { StyleSheet, View } from 'react-native';
import Mapbox, { MapView, Camera, PointAnnotation } from '@rnmapbox/maps';

Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

export default function CustomColorMarker() {
  return (
    <View style={styles.container}>
      <MapView style={styles.map}>
        <Camera zoomLevel={14} centerCoordinate={[106.8272, -6.1754]} />
        <PointAnnotation id="marker2" coordinate={[106.8272, -6.1754]}>
          <View style={styles.marker} />
        </PointAnnotation>
      </MapView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  map: { flex: 1 },
  marker: {
    width: 20,
    height: 20,
    borderRadius: 10,
    backgroundColor: '#E63946', // merah
    borderWidth: 2,
    borderColor: '#fff',
  },
});

Using an Image as Marker

If you want something more visual — like a custom pin icon — simply replace the marker view with an image.

import React from 'react';
import { StyleSheet, View, Image } from 'react-native';
import Mapbox, { MapView, Camera, PointAnnotation } from '@rnmapbox/maps';

Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

export default function ImageMarker() {
  return (
    <View style={styles.container}>
      <MapView style={styles.map}>
        <Camera zoomLevel={14} centerCoordinate={[106.8272, -6.1754]} />
        <PointAnnotation id="marker3" coordinate={[106.8272, -6.1754]}>
          <Image
            source={require('./assets/pin.png')} // pastikan ada di folder assets
            style={styles.markerImage}
          />
        </PointAnnotation>
      </MapView>
    </View>
  );
}

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

Changing the Map Style

Mapbox offers multiple prebuilt styles. You can switch between light, dark, satellite, and more using styleURL.

import React from 'react';
import { View, StyleSheet } from 'react-native';
import Mapbox, { MapView, Camera, PointAnnotation } from '@rnmapbox/maps';

Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

export default function DarkMap() {
  return (
    <View style={styles.container}>
      <MapView
        styleURL={Mapbox.StyleURL.Dark} // 👉 Ganti peta menjadi dark mode
        style={styles.map}
      >
        <Camera
          zoomLevel={12}
          centerCoordinate={[106.8272, -6.1751]}
        />
        <PointAnnotation id="marker1" coordinate={[106.8272, -6.1754]} />
      </MapView>
    </View>
  );
}

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

You can also experiment with different built-in map styles provided by Mapbox.

Here are some of the options you can try:

  • Mapbox.StyleURL.Street
  • Mapbox.StyleURL.Outdoors
  • Mapbox.StyleURL.Light
  • Mapbox.StyleURL.Dark
  • Mapbox.StyleURL.Satellite
  • Mapbox.StyleURL.SatelliteStreet
  • Mapbox.StyleURL.TrafficDay
  • Mapbox.StyleURL.TrafficNight

Each style gives your map a different look and feel — from minimalist light themes to high-contrast dark modes, or even real satellite imagery with road overlays.

Alternatively, you can also specify the full style URL directly using the mapbox:// syntax. Here’s an example:

import React from 'react';
import { View, StyleSheet } from 'react-native';
import Mapbox, { MapView, Camera, PointAnnotation } from '@rnmapbox/maps';

Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

export default function DarkMap() {
  return (
    <View style={styles.container}>
      <MapView
        styleURL={'mapbox://styles/mapbox/light-v11'} // 👉 Ganti style peta
        style={styles.map}
      >
        <Camera
          zoomLevel={12}
          centerCoordinate={[106.8272, -6.1751]}
        />
        <PointAnnotation id="marker1" coordinate={[106.8272, -6.1754]} />
      </MapView>
    </View>
  );
}

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

You can replace the style URL with any of the following Mapbox presets:

  • mapbox://styles/mapbox/streets-v12
  • mapbox://styles/mapbox/outdoors-v12
  • mapbox://styles/mapbox/light-v11
  • mapbox://styles/mapbox/dark-v11
  • mapbox://styles/mapbox/satellite-v9
  • mapbox://styles/mapbox/satellite-streets-v12
  • mapbox://styles/mapbox/navigation-day-v1
  • mapbox://styles/mapbox/navigation-night-v1
  • mapbox://styles/mapbox/standard
  • mapbox://styles/mapbox/standard-satellite

Getting the current location

To display the user’s current location and move the camera automatically, use UserLocation and Camera with a reference.

import React, { useEffect, useRef } from 'react';
import { View, StyleSheet, PermissionsAndroid, Platform } from 'react-native';
import Mapbox, { MapView, Camera, UserLocation } from '@rnmapbox/maps';

// Ganti dengan token kamu
Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

export default function CurrentLocationMap() {
      const cameraRef = useRef(null);

  // ✅ Minta izin lokasi (khusus Android)
  useEffect(() => {
    const requestLocationPermission = async () => {
      if (Platform.OS === 'android') {
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          {
            title: 'Izin Lokasi',
            message: 'Aplikasi memerlukan akses lokasi untuk menampilkan posisi Anda.',
            buttonNeutral: 'Tanya Nanti',
            buttonNegative: 'Batal',
            buttonPositive: 'OK',
          }
        );
        if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
          console.warn('Izin lokasi tidak diberikan');
        }
      }
    };

    requestLocationPermission();
  }, []);

  return (
    <View style={styles.page}>
      <MapView
        style={styles.map}
        styleURL={Mapbox.StyleURL.Light} // peta gelap elegan
        logoEnabled={true}
      >
        {/* 🔵 Lokasi pengguna */}
        <UserLocation
          visible={true}
          onUpdate={(location) => {
            if (location?.coords) {
              const { longitude, latitude } = location.coords;
              // 🎯 Pindahkan kamera ke lokasi user
              cameraRef.current?.setCamera({
                centerCoordinate: [longitude, latitude],
                zoomLevel: 15,
                animationDuration: 1000,
              });
            }
          }}
        />

        {/* 🎥 Kamera dengan referensi */}
        <Camera ref={cameraRef} />
      </MapView>
    </View>
  );
}

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

Remember to request location permission on Android using PermissionsAndroid.

Displaying Multiple Markers

To render multiple points dynamically, map through an array of coordinates:

// src/screens/DynamicMarkers.js
import React from 'react';
import { View } from 'react-native';
import Mapbox, { MapView, Camera, PointAnnotation } from '@rnmapbox/maps';

Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

const markers = [
  { id: '1', coords: [106.8456, -6.2088] }, // Jakarta
  { id: '2', coords: [107.6191, -6.9175] }, // Bandung
  { id: '3', coords: [112.7508, -7.2575] }, // Surabaya
];

export default function DynamicMarkers() {
  return (
    <View style={{ flex: 1 }}>
      <MapView 
        style={{ flex: 1 }}
        styleURL={Mapbox.StyleURL.Light}
      >
        <Camera zoomLevel={4} centerCoordinate={[110, -6.5]} />
        {markers.map((marker) => (
          <PointAnnotation
            key={marker.id}
            id={marker.id}
            coordinate={marker.coords}
          />           

        ))}
      </MapView>
    </View>
  );
}

Custom Callout

You can show an information bubble (callout) when a user taps a marker. Here’s a simple approach that displays the callout outside the map, so it’s fully interactive.

// src/screens/CustomCallout.js
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, Dimensions } from 'react-native';
import Mapbox, { MapView, Camera, PointAnnotation } from '@rnmapbox/maps';

Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

export default function CustomCallout() {
  const [selected, setSelected] = useState(false);

  const marker = {
    id: '1',
    title: 'BMKG Jakarta',
    description: 'Stasiun Meteorologi Kemayoran',
    coords: [106.8394085, -6.1560067],
  };

  return (
    <View style={{ flex: 1 }}>
      <MapView style={{ flex: 1 }}>
        <Camera zoomLevel={12} centerCoordinate={marker.coords} />

        <PointAnnotation
          id={marker.id}
          coordinate={marker.coords}
          onSelected={() => setSelected(true)}
        />          
      </MapView>

      {/* ✅ Callout di luar peta agar bisa diklik */}
      {selected && (
        <View style={styles.calloutContainer}>
          <View style={styles.callout}>
            <Text style={{ fontWeight: 'bold' }}>{marker.title}</Text>
            <Text style={{ fontSize: 12 }}>{marker.description}</Text>
            <TouchableOpacity onPress={() => setSelected(false)} style={{ marginTop: 6 }}>
              <Text style={{ color: 'blue', fontSize: 12 }}>Tutup</Text>
            </TouchableOpacity>
          </View>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({  
  calloutContainer: {
    position: 'absolute',
    bottom: 100, // posisi relatif dari bawah layar
    left: Dimensions.get('window').width / 2 - 100,
  },
  callout: {
    width: 200,
    backgroundColor: 'white',
    padding: 10,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOpacity: 0.3,
    shadowRadius: 4,
  },
});

Drawing a Polyline (Route)

You can visualize paths or routes between points using a LineLayer inside a ShapeSource.

// src/screens/PolylineRoute.js
import React from 'react';
import { View } from 'react-native';
import Mapbox, { MapView, Camera, ShapeSource, LineLayer } from '@rnmapbox/maps';

Mapbox.setAccessToken('YOUR_MAPBOX_ACCESS_TOKEN_HERE');

const routeGeoJSON = {
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      geometry: {
        type: 'LineString',
        coordinates: [
          [106.8456, -6.2088], // Jakarta
          [107.6191, -6.9175], // Bandung
          [110.3671, -7.8014], // Yogyakarta
          [112.7508, -7.2575], // Surabaya
        ],
      },
    },
  ],
};

export default function PolylineRoute() {
  return (
    <View style={{ flex: 1 }}>
      <MapView style={{ flex: 1 }}>
        <Camera zoomLevel={5} centerCoordinate={[110, -7]} />
        <ShapeSource id="routeSource" shape={routeGeoJSON}>
          <LineLayer
            id="routeLine"
            style={{
              lineColor: '#1E90FF',
              lineWidth: 4,
              lineCap: 'round',
              lineJoin: 'round',
            }}
          />
        </ShapeSource>
      </MapView>
    </View>
  );
}

Conclusion

Mapbox brings a powerful, flexible, and beautifully designed mapping experience to React Native. With just a few components — MapView, Camera, PointAnnotation, and ShapeSource — you can build rich interactive maps that go far beyond what the default React Native MapView offers.

From dynamic markers to real-time user tracking and route visualization, Mapbox opens up a world of possibilities for location-based mobile apps.


메타데이터
post_id
b827a148c2dd
slug
exploring-mapbox-in-react-native-b827a148c2dd
url
https://medium.com/@mahisaajy/exploring-mapbox-in-react-native-b827a148c2dd
canonical_url
https://medium.com/@mahisaajy/exploring-mapbox-in-react-native-b827a148c2dd
author_url
https://medium.com/@mahisaajy
status
ok
fetched_at
2026-06-09 15:37:30