Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-Native-Maps don't seem to rerender once the geo location is acquired

I'm trying to create a simple app that loads a google map (using airbnb's react-native-maps library) and shows the user's current location. What I'm seeing is that the map always shows the default initial position rather than re-rendering once the user's location is acquired.

I'm using React 0.42 and testing only on iOS. Here is some code to clarify:

1.) I set an initial state

state = {
      region: {
        latitude: 52,
        longitude: 5,
        latitudeDelta: 0.0922,
        longitudeDelta: 0.0421
      }
  }

2.) I get the user's location within componentDidMount

componentDidMount() {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        this.setState({
          region: {
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
            latitudeDelta: 0.01,
            longitudeDelta: 0.0011
          }
        });
      },
      (error) => alert(JSON.stringify(error)),
      {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
    );
  }

3.) With render, I display the map with the initial region, and expect that region to change once the user's location is acquired

render() {
    return (
     <View style={{ flex: 1 }}>
       <View style={{backgroundColor: 'coral', height: 70, justifyContent: 'center', alignItems: 'center'}}>
         <Text>
            <Text>longitude: {this.state.region.longitude}</Text>
            <Text>latitude: {this.state.region.latitude}</Text>
        </Text>
       </View>
       <View style={styles.container}>
         <MapView
           provider={PROVIDER_GOOGLE}
           style={styles.map}
           initialRegion={this.state.region}
           region={this.state.region}
           onRegionChange={this.onRegionChange}
           onRegionChangeComplete={this.reloadEntities}
         />
       </View>
     </View>
   );
 }

Here is the onRegionChange, just updates the state with the new region, which I believe will cause a re-render

onRegionChange = (region) => {
  this.setState({ region });
}

NOTE: The longitude and latitude text values do update as the region on the map changes, and they have they are updated once the user's location is acquired.

So I'm a bit confused as to why the map does not change what it's showing once the user's location is acquired. Any help would be much appreciated!

Update: I've taken a look at this thread: https://github.com/airbnb/react-native-maps/issues/43 and it seems to revolve mainly around Android, but I did try to remove the enableHighAccuracy option with no luck.

like image 237
Rudy Avatar asked Mar 09 '17 03:03

Rudy


2 Answers

Set the region of the MapView with the value of your region state this.state.region.

You need to get the current position and setting it to the region and then to use the watchPosition function to get the coordinates everytime the device detects there's a change in the location, this time set the new values to your region state.

This would work this way

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

const { width, height } = Dimensions.get('window');
const ASPECT_RATIO    = width / height;
const LATITUDE        = 37.78825;
const LONGITUDE       = -122.4324;
const LATITUDE_DELTA  = 0.0122;
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;
const SPACE           = 0.01;

class Test extends Component {
  constructor() {
    super();
    this.state = {
      region: {
        latitude: LATITUDE,
        longitude: LONGITUDE,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA
      }
    }
  }

componentDidMount() {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        this.setState({
          region: {
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
            latitudeDelta: LATITUDE_DELTA,
            longitudeDelta: LONGITUDE_DELTA,
            accuracy: position.coords.accuracy
          }
        });
      },
      (error) => alert(error.message),
      {timeout: 10000}
    );

    this.watchID = navigator.geolocation.watchPosition((position) => {
      const newRegion = {
        latitude: position.coords.latitude,
        longitude: position.coords.longitude,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA,
        accuracy: position.coords.accuracy
      }
      this.setState({newRegion});
    });
  }

  componentWillUnmount() {
    navigator.geolocation.clearWatch(this.watchID);
  }

  render() {
    return (
      <View style={styles.container}>
        <MapView
          style={styles.map}
          region={this.state.region}
          showsUserLocation={true}
          followUserLocation={true}>
        </MapView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  map: {
    ...StyleSheet.absoluteFillObject,
  },
});

AppRegistry.registerComponent('Russia terrorist state', () => Test);

Be sure to enable showsUserLocation and followUserLocation in the MapView, this way the app will ask the user current location.

followUserLocation depends on showUserLocation.

Constant longitude and latitude are only as example.

like image 63
Sebastian Palma Avatar answered Nov 10 '22 00:11

Sebastian Palma


You should not use initialRegion prop with region prop together:

Use this prop instead of region only if you don't want to control the viewport of the map besides the initial region.

Source

It should work after you remove the initialRegion prop.

like image 2
Zsolt Avatar answered Nov 09 '22 23:11

Zsolt