Search code examples
react-nativereact-navigationreact-native-maps

Update react-native-maps on React Navigation


I'm building an app with react native and Expo, using react native maps, and also react navigation V5 for navigating between screens.

When I update a state, I use setState, since I'm using a class, and the App renders, so far so good.

I use location in the maps, so I have to wait for permission to get the location of the users, by using the function: componentDidMount()

Problems ahead, now when I update a state in componentDidMount(), (it means, when the location is done) it renders in the App, but not the screen, but my map is in the initial screen, and it does not receive any updates.

this is how I proceed :

    export default class App extends React.Component {
      constructor() {
        super()
        this.state = {
          initialPosition: {
            latitude: 0,
            longitude: 0,
            latitudeDelta: 0,
            longitudeDelta: 0,
          },      
          initialMarker: {
            latitude: 0,
            longitude: 0,
          }     
        }
      }
    
      
      componentDidMount(){
        this.getLocationAsync();    
      }
      
      
      getLocationAsync = async () => {
        let { status } = await Permissions.askAsync(Permissions.LOCATION);
        if (status !== 'granted') {
          this.setState({
            errorMessage: 'Permission to access location was denied',
          });
        }
    
        let location = await Location.getCurrentPositionAsync({accuracy:Location.Accuracy.BestForNavigation});
        const { latitude , longitude } = location.coords
        this.getGeocodeAsync({latitude, longitude})
       
       this.setState({ initialPosition: {
            latitude: latitude,
            longitude: longitude,
            latitudeDelta: 0,
            longitudeDelta: 0,
          }});    
          
          this.setState({ initialMarker: {
            latitude: latitude,
            longitude: longitude,
          }});
        
    
        console.log('GOT LOCATION')
    
      };

the App render part:

render(){ 
  return (
    <NavigationContainer>
      <Drawer.Navigator initialRouteName="Home">
        <Drawer.Screen name="HISTORIQUE" component={this.HomeScreen}/>
        <Drawer.Screen name="MOYENS DE PAYEMENT" component={this.NotificationsScreen} />
        <Drawer.Screen name="PARRAINAGE" component={this.NotificationsScreen} />
        <Drawer.Screen name="CONSTACTER PASS" component={this.NotificationsScreen} />
        <Drawer.Screen name="PARAMÈTRES" component={this.NotificationsScreen} />
        <Drawer.Screen name="DÉCONNEXION" component={this.NotificationsScreen} />
      </Drawer.Navigator>
    </NavigationContainer>
    
    );   
 }

I use : this.state.initialPosition, in the screen, this works at first load, but when the componentDidMount() is donne and update the state, it doesn't update in the screen.

the Home screen used for maps:

HomeScreen =({ navigation}) => {

     return (
        <View style={styles.container}>
          <MapView
            style={styles.map}
            initialRegion={this.state.initialPosition}           
            region={this.state.initialPosition}>
                
                <Marker
                    coordinate={this.state.initialMarker}
                    title={"Your location"}
                >   

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

Current behavior : Marker and map position : is zero, or at the middle of the ocean.

Wanted behavior : Marker and map position: at my current location.

My question is: How can I update the position of the map, after location data is done ?

In another way : How can I update a variable inside a screen after componentDidMount() function is done ?


Solution

  • Problem solved !

    1. Use a class instead of a function:

      class HomeScreen extends React.Component { ... }

      instead of:

      HomeScreen =({ navigation}) => {...}

    2. Put the state and componentDidMount() function inside the HomeScreen class.

    3. Call the component as class not a function:

      <Drawer.Screen name="HOME" component={HomeScreen}/>

    4. To use the navigation object : set it in the render() of the HomeScreen class:

      const { navigation } = this.props;

    check React Navigation docs