How to do it...

  1. We'll start by opening App.js and adding our imports:
import React from 'react';
import {
Location,
Permissions,
MapView,
Marker
} from 'expo';
import {
StyleSheet,
Text,
View,
} from 'react-native';
  1. Next, let's define the App class and the initial state. In this recipe, state will only need to keep track of the user's location, which we initialize to null:
export default class App extends Component {
state = {
location: null
}
// Defined in following steps
}
  1. Next, we'll define the componentDidMount life cycle hook, which will ask the user to grant permission to access the user's location via the device's geolocation. If the user grants the app permission to use its location, the return object will have a status property with the value 'granted'. If granted, we'll get the user's location with this.getLocation, defined in the next step:
  async componentDidMount() {
const permission = await Permissions.askAsync(Permissions.LOCATION);
if (permission.status === 'granted') {
this.getLocation();
}
}
  1. The getLocation function is simple. It grabs the location information from the device's GPS using the getCurrentPositionAsync method of the Location component, then saves that location information to state. That information contains the latitude and longitude of the user, which we'll use when we render the map:
  async getLocation() {
let location = await Location.getCurrentPositionAsync({});
this.setState({
location
});
}
  1. Now, let's use that location information to render our map. First, we'll check that a location has been saved on state. If so, we'll render the MapView, and otherwise render null. The only property we need to set to render our map is the initialRegion property, which defines the location the map should display when it is first rendered. We'll pass this property on the object with the latitude and longitude saved to state, and define a starting zoom level with latitudeDelta and longitudeDelta:
  renderMap() {
return this.state.location ?
<MapView
style={styles.map}
initialRegion={{
latitude: this.state.location.coords.latitude,
longitude: this.state.location.coords.longitude,
latitudeDelta: 0.09,
longitudeDelta: 0.04,
}}
>
// Map marker is defined in next step
</MapView> : null
}
  1. Within the MapView, we'll need to add a marker at the user's current location. The Marker component is part of the MapView parent component, so in the JSX we'll define a MapView.Marker child element of the MapView element. This element takes the user's location, a title, and description for displaying when the icon is tapped, and a custom image via the image property:
      <MapView
style={styles.map}
initialRegion={{
latitude: this.state.location.coords.latitude,
longitude: this.state.location.coords.longitude,
latitudeDelta: 0.09,
longitudeDelta: 0.04,
}}
>
<MapView.Marker
coordinate={this.state.location.coords}
title={"User Location"}
description={"You are here!"}
image={require('./assets/you-are-here.png')}
/>
</MapView> : null
  1. Now, let's define our render function. It simply renders the map within a containing View element:
 render() {
return (
<View style={styles.container}>
{this.renderMap()}
</View>
);
}
  1. Lastly, let's add our styles. We'll set flex to 1 on both the container and the map, so that both fill the screen:
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
map: {
flex: 1
}
});
  1. Now, if we open the app, we'll see a map rendered with our custom user icon at the location provided by the device! Unfortunately, Google Maps integration may not work in the Android emulator, so a real device may be needed to test the Android implementation of the app. Check out the There's more... section at the end of this recipe for more information. Don't be surprised that the iOS app running on a simulator displays the user's location in San Francisco; this is due to how Xcode location defaults work. Run it on a real iOS device to see it render your location: