By the end of this lesson, you will:
Location-based apps power some of the most viral mobile experiences. From Pokemon GO to Uber, apps that leverage maps create engagement by connecting digital experiences to physical places. In this lesson, we'll explore how to integrate Google Maps into your React Native app using react-native-maps.
The Google Maps SDK gives you professional-grade mapping capabilities that billions of users already trust. Whether you're building a delivery app, a social check-in platform, or a location-based game, mastering maps is essential for creating apps people share.
The react-native-maps library provides a unified API for both Google Maps (Android) and Apple Maps (iOS). Here's how to integrate it:
// Install the package
// npx expo install react-native-maps
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,
latitudeDelta: 0.0421,
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
map: {
width: '100%',
height: '100%',
},
});
💡 Tip: Always set
flex: 1on the container and explicit width/height on the MapView to ensure proper rendering.
The map's visible area is controlled by a region object with four key properties:
const region = {
latitude: 37.78825, // Center latitude
longitude: -122.4324, // Center longitude
latitudeDelta: 0.0922, // Vertical span (degrees)
longitudeDelta: 0.0421, // Horizontal span (degrees)
};
Latitude/Longitude: Geographic coordinates in decimal degrees
Deltas: Control the zoom level
// Zoom levels comparison
const cityView = { latitudeDelta: 0.1, longitudeDelta: 0.1 }; // Wide area
const streetView = { latitudeDelta: 0.01, longitudeDelta: 0.01 }; // Few blocks
const buildingView = { latitudeDelta: 0.002, longitudeDelta: 0.002 }; // Close-up
Google Maps offers multiple map types for different use cases:
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
export default function StyledMapScreen() {
return (
<MapView
provider={PROVIDER_GOOGLE}
mapType="standard" // Options: standard, satellite, hybrid, terrain
style={styles.map}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
/>
);
}
Map Types Explained:
Create custom map styles using Google's Map Styling Wizard:
import MapView from 'react-native-maps';
import { darkMapStyle } from './mapStyles';
export default function DarkMapScreen() {
return (
<MapView
style={styles.map}
customMapStyle={darkMapStyle}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
/>
);
}
// mapStyles.js
export const darkMapStyle = [
{
elementType: 'geometry',
stylers: [{ color: '#242f3e' }],
},
{
elementType: 'labels.text.stroke',
stylers: [{ color: '#242f3e' }],
},
{
elementType: 'labels.text.fill',
stylers: [{ color: '#746855' }],
},
// Add more styling rules...
];
💡 Tip: Use Google Maps Styling Wizard to visually design custom styles, then export the JSON.
Control the map's camera programmatically for smooth user experiences:
import { useRef } from 'react';
import MapView from 'react-native-maps';
import { Button, View } from 'react-native';
export default function AnimatedMapScreen() {
const mapRef = useRef(null);
const animateToLocation = () => {
mapRef.current?.animateToRegion(
{
latitude: 40.7128,
longitude: -74.0060,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
},
1000 // Animation duration in milliseconds
);
};
const jumpToLocation = () => {
mapRef.current?.setCamera({
center: {
latitude: 51.5074,
longitude: -0.1278,
},
zoom: 12,
heading: 45, // Rotation angle
pitch: 60, // Tilt angle (0-90)
});
};
return (
<View style={styles.container}>
<MapView
ref={mapRef}
style={styles.map}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
/>
<View style={styles.buttonContainer}>
<Button title="Animate to NYC" onPress={animateToLocation} />
<Button title="Jump to London" onPress={jumpToLocation} />
</View>
</View>
);
}
Camera Methods:
animateToRegion(): Smooth animation with durationsetCamera(): Instant camera change with advanced optionsanimateCamera(): Smooth animation for camera objectControl what users can do with your map:
<MapView
style={styles.map}
initialRegion={region}
// Zoom controls
zoomEnabled={true}
zoomControlEnabled={true}
// Rotation and tilt
rotateEnabled={true}
pitchEnabled={true}
// User location
showsUserLocation={true}
followsUserLocation={false}
// UI elements
showsCompass={true}
showsScale={true}
showsBuildings={true}
showsTraffic={false}
showsIndoors={true}
// Gestures
scrollEnabled={true}
// Events
onPress={(e) => console.log(e.nativeEvent.coordinate)}
onRegionChangeComplete={(region) => console.log('New region:', region)}
/>
Here's a complete map screen with common features:
import { useState, useRef } from 'react';
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
import { StyleSheet, View, Button } from 'react-native';
export default function InteractiveMapScreen() {
const mapRef = useRef(null);
const [mapType, setMapType] = useState('standard');
const goToUserLocation = async () => {
// In a real app, get actual user location
const userLocation = {
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.02,
longitudeDelta: 0.02,
};
mapRef.current?.animateToRegion(userLocation, 1000);
};
const toggleMapType = () => {
setMapType(prev => prev === 'standard' ? 'satellite' : 'standard');
};
return (
<View style={styles.container}>
<MapView
ref={mapRef}
provider={PROVIDER_GOOGLE}
style={styles.map}
mapType={mapType}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
showsUserLocation={true}
showsMyLocationButton={true}
showsCompass={true}
onPress={(e) => {
console.log('Tapped coordinate:', e.nativeEvent.coordinate);
}}
/>
<View style={styles.controls}>
<Button title="My Location" onPress={goToUserLocation} />
<Button
title={`Switch to ${mapType === 'standard' ? 'Satellite' : 'Standard'}`}
onPress={toggleMapType}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
map: {
width: '100%',
height: '100%',
},
controls: {
position: 'absolute',
bottom: 20,
left: 20,
right: 20,
flexDirection: 'row',
justifyContent: 'space-between',
},
});
| Pitfall | Solution |
|---|---|
| Map not rendering | Ensure API key is configured in app.json and Google Cloud Console |
| Map appears gray | Check that latitude/longitude values are valid numbers |
| Zoom level inconsistent | Use both latitudeDelta and longitudeDelta for consistent zoom |
| Animation not working | Ensure you're using a ref and calling methods after map mounts |
| Performance issues | Avoid re-rendering MapView unnecessarily, use React.memo() |
react-native-maps offers a unified API across iOS and AndroidanimateToRegion() and setCamera()In the next lesson, we'll explore Custom Markers and Overlays, learning how to add pins, info windows, and clustering to make your map data visually engaging and organized.