I was trying get the current location using react-native-maps. This is my following code :
import MapView from 'react-native-maps';
import Geolocation from '#react-native-community/geolocation';
const [position, setPosition] = useState({
latitude: 10,
longitude: 10,
latitudeDelta: 0.001,
longitudeDelta: 0.001,
});
useEffect(() => {
Geolocation.getCurrentPosition(success, error, options);
}, []);
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
};
function success(pos) {
var crd = pos.coords;
setPosition({
latitude: crd.latitude,
longitude: crd.longitude,
latitudeDelta: 0.0421,
longitudeDelta: 0.0421,
});
}
function error(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
}
return (
<MapView
style={styles.map}
initialRegion={position}
showsUserLocation={true}
>
</MapView>
Now if I remove the property initialRegion, the map is working perfectly fine. But with the above code, I am getting a white screen without any error.
Any help will be appreciated.
I think the problem with your code is that getCurrentPosition is failing and since your initial coordinates inside position are very zoomed in, it looks like it isn't showing anything.
Also make sure the google maps API is enabled and react-native-maps is configured correctly.
Here is how I got it working:
import React, {useState, useEffect} from 'react';
import {StyleSheet} from 'react-native';
import MapView from 'react-native-maps';
import Geolocation from '#react-native-community/geolocation';
const App = () => {
const [position, setPosition] = useState({
latitude: 10,
longitude: 10,
latitudeDelta: 0.001,
longitudeDelta: 0.001,
});
useEffect(() => {
Geolocation.getCurrentPosition((pos) => {
const crd = pos.coords;
setPosition({
latitude: crd.latitude,
longitude: crd.longitude,
latitudeDelta: 0.0421,
longitudeDelta: 0.0421,
});
}).catch((err) => {
console.log(err);
});
}, []);
return (
<MapView
style={styles.map}
initialRegion={position}
showsUserLocation={true}
/>
);
};
const styles = StyleSheet.create({
map: {
...StyleSheet.absoluteFillObject,
},
});
export default App;
Related
my react-native-maps MapView won't drag I can't seem to figure out why. I'm looking for an indicator of some sort to find it, but everything looks good to me and example code from other websites aren't helping. Is there something I'm missing?
import React, { Component } from 'react'
import {
StyleSheet,
Dimensions,
} from 'react-native'
import MapView, {
PROVIDER_GOOGLE
} from 'react-native-maps'
const { width, height } = Dimensions.get('window')
const ASPECT_RATIO = width / height
let LATITUDE = 40.3096
let LONGITUDE = -111.7071
let LATITUDE_DELTA = 0.0922
let LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO
class Maps extends Component<any, any> {
constructor(props: any) {
super(props)
this.state = {
region: {
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA
}
}
}
render() {
return (
<MapView
provider={PROVIDER_GOOGLE}
style={styles.map}
initialRegion={this.state.region}
onRegionChangeComplete={(region) => {this.setState(
region = {
latitude: region.latitude,
longitude: region.longitude,
latitudeDelta: region.latitudeDelta,
longitudeDelta: region.longitudeDelta
}
)}}
>
</MapView>
)
}
}
const styles = StyleSheet.create({
map: {
flex: 1,
minHeight: Dimensions.get('screen').height,
zIndex: 0
},
})
export default Maps
Is there something I'm doing wrong?
I am using React Native with Expo and this was originally a class based component but I converted it to a functional component because I want to use hooks. Now it is throwing an error shown in the screenshot. I am not sure what to do about the error?I have seen one other posting about this, but was a little lost (I am practicing with react). The component is basically a GPS with a marker! Thank you
import { View, Text, Animated, StyleSheet } from "react-native";
import MapView, { Marker, PROVIDER_GOOGLE } from "react-native-maps";
import React, { Component, useState } from "react";
import { MaterialCommunityIcons } from "react-native-vector-icons";
const LATITUDE = 18.7934829;
const LONGITUDE = 98.9867401;
const LATITUDE_DELTA = 0.009;
const LONGITUDE_DELTA = 0.009;
export default function MapLocation() {
const [location, setLocation] = useState({
isLoading: true,
latitude: LATITUDE,
longitude: LONGITUDE,
error: null,
});
var getMapRegion = () => ({
latitude: location.latitude,
longitude: location.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
});
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position);
setLocation({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
});
},
(error) => setLocation({ error: error.message }),
{ enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 }
);
navigator.geolocation.watchPosition((position) => {
const { latitude, longitude } = position.coords;
setLocation({ latitude, longitude });
});
const { isLoading } = location;
return (
<View style={{ flex: 1 }}>
<MapView
style={{ flex: 1 }}
provider={PROVIDER_GOOGLE}
region={getMapRegion}
showsUserLocation={true}
showsMyLocationButton={true}
>
<Marker coordinate={getMapRegion}>
<MaterialCommunityIcons name="egg" color={"white"} size={35} style={styles.shadow} />
</Marker>
<Marker
coordinate={{ latitude: 34.0198536, longitude: -80.923467 }}
pinColor="maroon"
title={"title"}
description={"description"}
>
<MaterialCommunityIcons name="school" color={"maroon"} size={40} style={styles.shadow} />
</Marker>
</MapView>
</View>
);
}
const styles = StyleSheet.create({
shadow: {
// transform: [{ rotateZ: "10deg" }],
shadowColor: "black",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 3,
},
});
There were several problems with my conversion to hooks using useState and useEffect. Both of which I solved with this guide on converting classes to functions. I was not using the "useEffect hook" in place of component did mount, I also did not have an empty array at the end of the useEffect hook which made it re-render constantly from what I understand.
Link to functional component conversion steps
I have a Mapview component and a Marker component inside it as below:
import React, {useContext, useState, useEffect} from 'react';
import {StyleSheet} from 'react-native';
import MapView, {PROVIDER_GOOGLE, Marker} from 'react-native-maps';
import Geolocation from '#react-native-community/geolocation';
import Toast from 'react-native-root-toast';
import {ThemeContext} from '~/utils/theme-context';
import {MAP_STYLE} from '~/utils/map.style';
import {Colors} from '~/styles';
const LATITUDE_DELTA = 0.01;
const LONGITUDE_DELTA = 0.01;
const Map = props => {
const themeContext = useContext(ThemeContext);
const mapStyle = MAP_STYLE;
let map = null;
let initialRegion = {
latitude: 35.78825,
longitude: -120.4324,
latitudeDelta: 0.015,
longitudeDelta: 0.0121,
};
const [region, setRegion] = useState(initialRegion);
const getCurrentPosition = Geolocation.getCurrentPosition;
const mapAnimation = map?.current.animateToRegion;
useEffect(() => {
const animate = location => {
if (map) {
mapAnimation(location, 1000);
}
};
const getPositionHandler = () => {
return getCurrentPosition(
info => {
const location = {
latitude: info.coords.latitude,
longitude: info.coords.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
};
animate(location);
setRegion(location);
},
error => {
Toast.show(error.message, {
backgroundColor: Colors.ERROR,
textColor: Colors.WHITE,
});
},
);
};
getPositionHandler();
}, [getCurrentPosition, mapAnimation, map]);
return (
<MapView
ref={map}
provider={PROVIDER_GOOGLE}
style={styles.map}
customMapStyle={themeContext.theme === 'light' ? [] : mapStyle}
region={region}>
<Marker
coordinate={{latitude: region.latitude, longitude: region.longitude}}
/>
</MapView>
);
};
const styles = StyleSheet.create({
map: {
...StyleSheet.absoluteFillObject,
borderRadius: 24,
},
});
export default Map;
I seems to stuck into this problem, even though it doesn't obstruct me from coding further, but the error speaks about memory leaks etc. which brings forth some concern on my side. Please help
I think your map ref might be the problem here. It get's initialized on every render and set to the ref of a newly rendered map. Although, if the map animates properly, then I wouldn't be sure.
Try using useRef instead and see if the warning goes away.
const map = useRef(null)
const mapAnimation = map.current?.animateToRegion;
Can anyone help me with this error?
I learn and copy the code from a YouTube tutorial about React-Native-Maps for displaying current location. Link: https://www.youtube.com/watch?v=MqLC0kOqrwk
The error is: Super expression must either be null or a function
I am using latest version of React-Native-Maps
React-Native-Maps Version :"^0.22.1",
This is my code.
import React from 'react';
import {
AppRegistry,
Component,
StyleSheet,
View,
Text,
screen,
Dimensions,
TouchableOpacity,
Platform,
} from 'react-native';
import MapView from 'react-native-maps';
import Strings from '../utils/Strings';
var styles = require('../../assets/files/Styles');
const {height, width} = Dimensions.get('window');
const SCREEN_HEIGHT = height
const SCREEN_WIDTH = width
const ASPECT_RATIO = width / height
const LATITUDE_DELTA = 0.00922;
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;
export default class Track extends Component {
static navigationOptions = {
title: `${Strings.ST6}`,
};
constructor(props) {
super(props)
this.state = {
initialPosition: {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0
},
markerPosition: {
latitude: 0,
longitude: 0
}
}
}
watchID = null
componentDidMount(){
navigator.geolocation.getCurrentPosition((position) => {
var lat = parseFloat(position.coords.latitude)
var long = parseFloat(position.coords.longitude)
var initialRegion = {
latitude: lat,
longitude: long,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGTITUDE_DELTA
}
this.getState({initialPosition: initialRegion})
this.getState({markerPosition: initialRegion})
},
(error) => alert(JSON.stringify(error)),
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000})
this.watchID = navigator.geolocation.watchPosition((position) => {
var lat = parseFloat(position.coords.latitude)
var long = parseFloat(position,coords,longitude)
var lastRegion = {
latitude: lat,
longitude: long,
longitudeDelta: LONGTITUDE_DELTA,
latitudeDelta: LATITUDE_DELTA
}
this.setState({initialPosition: lastRegion})
this.setState({markerPosition: lastRegion})
})
}
componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchID)
}
render() {
return(
<View style={style.container}>
<MapView
style={styles.map}
region={this.state.initialPosition}>
<MapView.Marker>
coordinate={this.state.markerPosition}
<View Style={styles.radius}>
<View Style={styles.marker}>
</View>
</View>
</MapView.Marker>
</MapView>
</View>
);
}
}
I guess the error is somewhere around
constructor(props) {
super(props)
But I don't see a error here, the super should be fine, the result is same even I remove the (props).
On your code class Track extends Component you forget to call the react properties. please change your code to be class Track extends React.Component.
Because you just call the Component, and react doesn't know where 'Component' comes from
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.
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.
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.
It's also important to get rid of onRegionChangeComplete={this.reloadEntities}.
Every time the region changes, react-native will reload and default back to the initial state you declared in your constructor.