the <App>
component will mount first and then after that componentDidMount()
will be called as its name says. The reason you are getting this error is that when <App>
will be mounted for the first time the this.state.where
will be null.
To avoid this error you can do the following trick:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'
import Constants from "expo-constants";
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import { render } from 'react-dom';
import 'leaflet/dist/leaflet.css';
export default class App extends React.Component {
constructor() {
super();
this.state = {
ready: false,
where: { lat: null, lng: null },
error: null
}
}
componentDidMount() {
let geoOptions = {
enableHighAccuracy: true,
timeOut: 20000,
maximumAge: 60 * 60 * 24
};
this.setState({ ready: false, error: null });
navigator.geolocation.getCurrentPosition(this.geoSuccess, this.geoFailure, geoOptions);
}
geoSuccess = (position) => {
console.log(position.coords.latitude);
this.setState({
ready: true,
where: { lat: position.coords.latitude, lng: position.coords.longitude }
})
}
geoFailure = (err) => {
this.setState({ error: err.message });
}
render() {
return (
<>
{( this.state.where.lng != null && this.state.where.lat != null) &&
<MapContainer
style={{ height: '100%', width: '100%' }}
center={[ this.state.where?.lat , this.state.where?.lng]}
zoom="30"
scrollWheelZoom={true}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
}
</>
);
}
}
In the above code the MapContainer
will not render until you will get this.state.where
in the state.
UPDATE
Please look at the previous code as well I updated the checks to render the map.
You can also check the lng lat
by console.log()
and if you are not getting them then you can use another package called @react-native-community/geolocation
which was working for me;
import 'react-native-gesture-handler';
import React, { Component } from 'react';
import {
SafeAreaView, StyleSheet, ScrollView, View, StatusBar, Dimensions, Image, TouchableOpacity, TextInput, ToastAndroid, ActivityIndicator,
LogBox, Keyboard, Modal, TouchableHighlight, PermissionsAndroid, ImageBackground, FlatList, AppState, Linking
} from 'react-native';
import Geolocation from '@react-native-community/geolocation'
export class SignUpScreen extends Component {
constructor() {
super()
this.state = {
longitude: '',
latitude: '',
locationAccuracy: '',
}
}
componentDidMount() {
Geolocation.getCurrentPosition((info) => {
this.setState({
longitude: info.coords.longitude,
latitude: info.coords.latitude,
locationAccuracy: info.coords.accuracy,
})
})
}
render() {
console.log(this.state)
return (
<View>
{this.state.longitude != '' && this.state.latitude != '' &&
<>
{/* YOUR MAP */}
</>
}
</View>
)
}
}
export default class App extends Component {
render() {
return (
<SignUpScreen />
);
}
}