skills/imfa-solutions/skills/react-native-maps-skill

react-native-maps-skill

SKILL.md

React Native Maps — Best Practices & Complete Guide

react-native-maps 1.26.20+ / Expo SDK 54/55 / React Native 0.81.1+ / New Architecture Compatible

Critical Rules

  1. Always use npx expo install react-native-maps — ensures version compatibility with your Expo SDK.
  2. Never commit API keys — use environment variables via app.config.js with process.env.
  3. Always restrict API keys — Android: package name + SHA-1; iOS: bundle identifier; API: Maps SDK only.
  4. Always run npx expo prebuild --clean after changing map config in app.json/app.config.js.
  5. Use initialRegion not region unless you need controlled map positioning — region causes re-renders on every pan.
  6. Memoize marker arrays with useMemo — recreating marker elements every render causes lag.
  7. Use React.memo for custom marker components — prevents unnecessary re-renders of all markers.
  8. Use clustering for 50+ markers — install react-native-map-clustering to avoid frame drops.
  9. Handle the null map ref — always check mapRef.current before calling methods like animateToRegion.
  10. Request location permissions before enabling showsUserLocation — otherwise the map silently fails on iOS.

Version Compatibility

react-native-maps React Native Expo SDK New Architecture
1.26.1+ >= 0.81.1 54/55 Supported
1.26.0 >= 0.76 53 Supported
1.14.0 - 1.20.1 >= 0.74 50-52 Old Arch only
< 1.14.0 >= 0.64.3 < 50 Old Arch only

Installation

# Expo (recommended — pins compatible version)
npx expo install react-native-maps

# For location features
npx expo install expo-location

TypeScript definitions are bundled — no @types package needed.

Quick Start

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

export default function MapScreen() {
  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: { width: '100%', height: '100%' },
});

Map Providers

  • Default (no provider prop): Apple Maps on iOS, Google Maps on Android
  • PROVIDER_GOOGLE: Google Maps on both platforms (requires API keys)
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';

<MapView provider={PROVIDER_GOOGLE} style={styles.map} />

Apple Maps requires no API key. Google Maps requires API keys for both platforms — see references/google-maps-setup.md.

API Key Configuration (Google Maps)

Configure via the Expo config plugin in app.config.js:

// app.config.js
import 'dotenv/config';

export default {
  expo: {
    plugins: [
      [
        'react-native-maps',
        {
          androidGoogleMapsApiKey: process.env.GOOGLE_MAPS_ANDROID_KEY,
          iosGoogleMapsApiKey: process.env.GOOGLE_MAPS_IOS_KEY,
        },
      ],
    ],
  },
};

The old android.config.googleMaps.apiKey syntax is deprecated — always use the plugin config.

After changing config, rebuild:

npx expo prebuild --clean
npx expo run:android  # or run:ios

For full setup details (Cloud Console, SHA-1, key restrictions), see references/google-maps-setup.md.

Core Components

Markers

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

<MapView style={styles.map} initialRegion={region}>
  <Marker
    coordinate={{ latitude: 37.78825, longitude: -122.4324 }}
    title="San Francisco"
    description="A beautiful city"
  />
</MapView>

Custom marker views:

<Marker coordinate={coordinate}>
  <View style={styles.customMarker}>
    <Image source={require('./marker.png')} style={{ width: 40, height: 40 }} />
  </View>
</Marker>

Use local images over remote URLs for markers — they load faster and avoid flicker.

Polylines & Polygons

import { Polyline, Polygon } from 'react-native-maps';

<Polyline
  coordinates={routeCoords}
  strokeColor="#000"
  strokeWidth={3}
/>

<Polygon
  coordinates={areaCoords}
  fillColor="rgba(255, 0, 0, 0.3)"
  strokeColor="red"
  strokeWidth={2}
/>

Heatmaps, GeoJSON, Circles

See references/advanced-features.md for Heatmap, Geojson, Circle, Callout, Overlay, and custom tile layers.

Map Ref & Programmatic Control

const mapRef = useRef<MapView>(null);

// Animate to a region
mapRef.current?.animateToRegion(targetRegion, 1000);

// Fit map to show all coordinates
mapRef.current?.fitToCoordinates(coordinates, {
  edgePadding: { top: 50, right: 50, bottom: 50, left: 50 },
  animated: true,
});

User Location

import * as Location from 'expo-location';

// Request permissions first
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') return;

// Then enable on map
<MapView
  showsUserLocation={true}
  followsUserLocation={true}
  showsMyLocationButton={true}
/>

For iOS, add to app.json:

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSLocationWhenInUseUsageDescription": "Show your position on the map."
      }
    }
  }
}

For real-time tracking and background location, see references/advanced-features.md.

Performance Optimization

  1. Memoize markers: Wrap marker arrays in useMemo keyed on the data source
  2. Use React.memo for custom marker components
  3. Cluster markers: Use react-native-map-clustering for 50+ markers
  4. Filter visible markers: Only render markers within the current region bounds
  5. Prefer native marker images over custom React views for large datasets
  6. Use initialRegion over region to avoid controlled-component re-render overhead

See references/performance.md for detailed patterns and code examples.

Common Issues & Debugging

Symptom Likely Cause Fix
Blank/gray map Missing or invalid API key Check key in plugin config, verify billing enabled
Gray map with logo Wrong SHA-1 or bundle ID restriction Regenerate key with correct restrictions
Crash on load Missing prebuild after config change npx expo prebuild --clean then rebuild
Custom markers invisible Image not loaded or wrong size Use local images, set explicit width/height
Dark mode unexpected Android auto dark mode Set userInterfaceStyle="light" on MapView
Build failure (Fabric) Incompatible versions Ensure react-native-maps >= 1.26.1 for SDK 54+
Lag with many markers Too many rendered components Use clustering + memoization

For detailed troubleshooting with step-by-step fixes, see references/troubleshooting.md.

Production Deployment

Pre-deployment checklist:

  • API keys restricted to production package name / bundle ID
  • Play Store SHA-1 (from App Signing) added to Android key
  • Location permissions declared in app.json
  • Tested on physical devices (maps don't work well in simulators)
  • No hardcoded API keys in source code

For full EAS Build configuration and store submission, see references/production.md.

Reference Files

Read these for detailed guidance on specific topics:

File When to read
references/google-maps-setup.md Setting up Google Cloud, API keys, SHA-1, key restrictions
references/advanced-features.md Heatmaps, GeoJSON, location tracking, custom styling, clustering
references/performance.md Marker optimization, clustering, lazy loading, animation patterns
references/troubleshooting.md Debugging blank maps, crashes, build failures, marker issues
references/production.md EAS Build config, store deployment, production API key setup
Weekly Installs
2
GitHub Stars
1
First Seen
6 days ago
Installed on
amp2
cline2
openclaw2
opencode2
cursor2
kimi-cli2