React Native Maps - Null Object Reference - react-native-maps

I'm following this tutorial on React Native Maps: https://www.youtube.com/watch?v=MqLC0kOqrwk&t=1s
My code is near identical to the tutors (I didn't use MapView.Markers) but I get this error: Attempt to invoke interface method 'boolean
abi19_0_0.com.facebook.react.bridge.ReadableMap.hasKey(java.lang.String)' on a null object reference
Here is my code:
import React from 'react';
import { View, Text, StyleSheet, Dimensions } from 'react-native';
import MapView from 'react-native-maps';
const { width, height } = Dimensions.get ('window')
const SCREEN_HEIGHT = height
const SCREEN_WIDTH = width
const ASPECT_RATIO = width / height
const LATITUDE_DELTA = 0.0922
const LONGTITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO
export default class MapScreen extends React.Component {
constructor (props) {
super (props)
this.state = {
initialPosition: {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0,
}
}
}
watchID: ?number = 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.setState ({ initialPosition: 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,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGTITUDE_DELTA
}
this.setState ({ initialPosition: lastRegion })
})
}
componentWillUnmount () {
navigator.geolocation.clearWatch (this.watchID)
}
render () {
return (
<MapView
style = { styles.mapContainer }
region = {this.state.initialPosition}
/>
);
}
}

Managed to get this working in a new react-native init project (RN 0.47.1, RNMaps 0.16.0) with the following added to ./android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="WHATEVERYOURAPIKEYIS" />

Related

Warning: Failed %s type: %s%s, prop, The prop `coordinate.longitude` is marked as required in `MapMarker`, but its value is `null`

can someone help me why is my marker not showing my location
when I remove lat and lon and replace it with actual latitude and longitude it works. when i console log lat and lon it comes up with the right coords but still has an error
import React from 'react'
import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps'
import { Entypo } from "#expo/vector-icons";
import { Feather } from "#expo/vector-icons";
import { Ionicons } from "#expo/vector-icons";
import { useNavigation } from '#react-navigation/native'
import * as Location from 'expo-location'
import { useState, useEffect } from 'react'
import { API, Auth, graphqlOperation } from 'aws-amplify';
const MapScreen = () => {
const [location, setLocation] = useState(null)
const [errMsg, setErrMsg] = useState(null)
const [lat, setLat] = useState(null)
const [lon, setLon] = useState(null)
useEffect(() => {
(async () => {
let {status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrMsg('Location denied!');
return;
}
let location = await Location.getCurrentPositionAsync()
setLocation(location)
setLat(location.coords.latitude)
setLon(location.coords.longitude)
console.log(location)
})();
}, []);
let text = 'Waiting..'
if (errMsg) {
text = errMsg;
} else if (location) {
text = JSON.stringify(location)
console.log(text)
}
const signOut = () => {
Auth.signOut();
};
const navigation = useNavigation()
return (
<View style={{marginTop:33}}>
<MapView
zoomEnabled={true}
provider={PROVIDER_GOOGLE}
style={{width:"100%", height:"100%"}}
initialRegion={{
latitude: -36.8491788,
longitude: 174.7574553,
latitudeDelta: 0.07,
longitudeDelta: 0
}}
>
<Marker
coordinate={{
latitude: lat,
longitude: lon,
}}
onPress={() => navigation.navigate('Home')}
>
</Marker>
</MapView>
i am getting the issue Warning: Failed %s type: %s%s, prop, The prop coordinate.longitude is marked as required in MapMarker, but its value is null.,

react native maps onPress marker drop problem

i have been trying to drop a pin on a map when i touch it, but i constantly get error:
error while updating property 'region' of a view managed by airmap null latitude
i have create constant markerPress and added it in MapView onPress, and then updated MapView.Marker
I have tried to change marker useState from null to empty object but didnt have any luck. Please help.
import React, {useState, useEffect} from 'react';
import {StyleSheet} from 'react-native';
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
import * as Location from "expo-location";
function HomeScreen({navigation}) {
const [location, setLocation] = useState(null);
const [mapRegion, setMapRegion] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
const [marker, setMarker] = useState(null)
const markerPress = (event) => {
setMarker({ marker: event.nativeEvent.coordinate })
}
useEffect(() => {
(async () => {
let { status } = await Location.requestPermissionsAsync();
if (status !== "granted") {
setErrorMsg("Permission to access location was denied");
}
let coordinates = await Location.getCurrentPositionAsync({});
setLocation(location);
setMapRegion({
longitude: coordinates.coords.longitude,
latitude: coordinates.coords.latitude,
longitudeDelta: 0.0922,
latitudeDelta: 0.0421
});
})();
}, []);
return (
<MapView
provider={PROVIDER_GOOGLE}
onPress={markerPress}
style={{flex:1}}
customMapStyle = { generatedMapStyle }
showsUserLocation={true}
followsUserLocation={true}
showsMyLocationButton={true}
initialRegion={mapRegion}>
{
marker &&
<MapView.Marker coordinate={marker} />
}
</MapView>
)
}
const styles = StyleSheet.create({
map: {
...StyleSheet.absoluteFillObject
}
})
You should change your setMarker call to this:
setMarker(event.nativeEvent.coordinate);
event.nativeEvent.coordinate is already a valid value for the coordinate prop.
So the correct object to pass to coordinate looks like this:
{
latitude: ...,
longitude: ...
}
and you passed this:
{
marker: {
latitude: ...,
longitude: ...
}
}

get current user location using google maps api with react native?

i'm currently working on a project using google maps api with react native, but i'm struggling to handle get current user location with redux, this is my action ,how can i fix it :
import MAPSActionTypes from "./mapsactiontypes";
export const currentlocation = () => {
return navigator.geolocation.getCurrentPosition(
(position) => {
console.log("wokeeey");
console.log(position);
{payload: position}
},
(error) => console.log(error)),
{ enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 },
};
I'm not sure what you're error is exactly, but I found an issue here on doing the exact same thing. It referred to a code sample you can find here, which I've reproduced below.
import React from 'react';
import {
Alert,
Platform,
StyleSheet
} from 'react-native';
import MapView from 'react-native-maps'
const LATITUDE_DELTA = 0.01;
const LONGITUDE_DELTA = 0.01;
const initialRegion = {
latitude: -37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}
class MyMapView extends React.Component {
map = null;
state = {
region: {
latitude: -37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
},
ready: true,
filteredMarkers: []
};
setRegion(region) {
if(this.state.ready) {
setTimeout(() => this.map.mapview.animateToRegion(region), 10);
}
//this.setState({ region });
}
componentDidMount() {
console.log('Component did mount');
this.getCurrentPosition();
}
getCurrentPosition() {
try {
navigator.geolocation.getCurrentPosition(
(position) => {
const region = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
};
this.setRegion(region);
},
(error) => {
//TODO: better design
switch (error.code) {
case 1:
if (Platform.OS === "ios") {
Alert.alert("", "Para ubicar tu locación habilita permiso para la aplicación en Ajustes - Privacidad - Localización");
} else {
Alert.alert("", "Para ubicar tu locación habilita permiso para la aplicación en Ajustes - Apps - ExampleApp - Localización");
}
break;
default:
Alert.alert("", "Error al detectar tu locación");
}
}
);
} catch(e) {
alert(e.message || "");
}
};
onMapReady = (e) => {
if(!this.state.ready) {
this.setState({ready: true});
}
};
onRegionChange = (region) => {
console.log('onRegionChange', region);
};
onRegionChangeComplete = (region) => {
console.log('onRegionChangeComplete', region);
};
render() {
const { region } = this.state;
const { children, renderMarker, markers } = this.props;
return (
<MapView
showsUserLocation
ref={ map => { this.map = map }}
data={markers}
initialRegion={initialRegion}
renderMarker={renderMarker}
onMapReady={this.onMapReady}
showsMyLocationButton={false}
onRegionChange={this.onRegionChange}
onRegionChangeComplete={this.onRegionChangeComplete}
style={StyleSheet.absoluteFill}
textStyle={{ color: '#bc8b00' }}
containerStyle={{backgroundColor: 'white', borderColor: '#BC8B00'}}>
{markers.map(renderMarker)}
{children && children || null}
</ClusteredMapView>
);
}
}
export default MyMapView;

Exception thrown while executing UI block: Invalid Region

I am trying to get the user location in my React Native app and move my MapView to that location. When the app loads, it shows the location (by default, not because of my action), but when the action is executed I get this error:
Exception thrown while executing UI block:
Invalid Region <center:+37.33233141, -122.03121860 span: +0.00044916, -0.05737702>
The region object being passed to my MapView (from my location actions) is
{
latitude: 37.33233141,
longitude: -122.0312186,
accuracy: 0.05,
latitudeDelta: 0.0004491555874955085,
longitudeDelta: -0.05737702242408729
};
I actually copied the code from an old project that had had the same problem and then at some point stopped having the problem.
Anyway, here's my code:
MapScreen.js
import React, { Component } from "react";
import MapView, { Marker, Callout } from "react-native-maps";
import { connect } from "react-redux";
import { View, Button, Text, Platform, TextInput } from "react-native";
const CurrentRegionMarker = ({ currentRegion }) => {
return currentRegion && currentRegion.showMarker ? (
<Marker coordinate={currentRegion} pinColor={"green"} />
) : null;
};
class MapScreen extends Component {
state = { region: null };
render() {
return (
<View style={styles.container}>
<MapView
style={{ flex: 1 }}
showsUserLocation={true}
region={this.props.currentRegion}
>
<CurrentRegionMarker currentRegion={this.props.currentRegion} />
</MapView>
</View>
);
}
}
export default connect(({ location }) => ({
currentRegion: location.currentRegion
}))(MapScreen);
locationActions.js
// #flow
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import type {
Location as LocationType,
LocationAction
} from "../reducers/locationReducer";
import type { Saga } from "redux-saga";
import { call, put, select, takeEvery, all } from "redux-saga/effects";
export function getLocationAsync(): LocationAction {
return { type: "USER_LOCATION_START" };
}
export function* getLocationSaga(): Saga<void> {
try {
const region = yield call(getUserLocation);
yield put({ type: "USER_LOCATION_SUCCESS", region });
} catch (error) {
yield put({ type: "USER_LOCATION_FAILURE", error: error.message });
}
}
async function getUserLocation(): LocationType {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
return console.warn("Permission to access location was denied");
}
let location = await Location.getCurrentPositionAsync({});
let { latitude, longitude } = location.coords;
let accuracy = 0.05;
let region = { latitude, longitude, accuracy };
console.log("direct", calculateRegion(region));
console.log("interpolated", { ...region, ...calculateRegion(region) });
return { ...calculateRegion(region), accuracy };
}
function calculateRegion({
latitude,
longitude,
accuracy = 0.05
}): LocationType {
const oneDegreeOfLongitudeInMeters = 111.32;
const circumference = 40075 / 360;
const latitudeDelta = accuracy / oneDegreeOfLongitudeInMeters;
const longitudeDelta = accuracy * (1 / Math.cos(latitude * circumference));
const region = { latitude, longitude, latitudeDelta, longitudeDelta };
return region;
}
export default function* locationSaga(): Saga<void> {
yield all([yield takeEvery("USER_LOCATION_START", getLocationSaga)]);
}
locationReducer.js
// #flow
const initialState: LocationState = {
currentRegion: {
latitude: 0,
longitude: 0,
latitudeDelta: 0.00922,
longitudeDelta: 0.00421,
showMarker: false
}
};
export default function dealsReducer(
state: LocationState = initialState,
action: LocationAction
): LocationState {
switch (action.type) {
case "USER_LOCATION_SUCCESS":
return { ...state, currentRegion: action.region };
case "USER_LOCATION_FAILURE":
return { ...state, error: action.error };
default:
return state;
}
}
export type Location = {
latitude: number,
longitude: number,
latitudeDelta: number,
longitudeDelta: number,
showMarker?: boolean
};
type LocationState = {
+currentRegion: Location,
+error: ?string
};
export type LocationAction =
| { type: "USER_LOCATION_START" }
| {
type: "USER_LOCATION_SUCCESS",
region: Location
}
| {
type: "USER_LOCATION_FAILURE",
error: string
};
Update: It appears that the longitudeDelta and latitudeDelta values were the problem. Right now I'm using hard-coded values for these, but I'm still not sure why this code is working as is in one app and not another.

React Native Null Reference - Maps & Markers (Android)

Hey Guys Iam getting an error on my Android Devices.
On Iphone it works very well I'am getting my Markers in maps but on Android iam getting this Error
Click for the Image
Since i upgraded the Code with geolib where iam filtering markers out which are not near to me it won't work on Android...
Anybody an idea?
this is my Code:
import React from 'react';
import MapView from 'react-native-maps';
import Marker from 'react-native-maps';
import Geolib from 'geolib';
import {
View,
Text,
StyleSheet,
Button,
} from "react-native";
const geolib = require('geolib');
class Grillplaetze extends React.Component {
constructor() {
super();
this.state = {
markers: [],
loaded: false
}
}
componentDidMount() {
this.getPosition();
}
getPosition(){
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position);
this.setState({
region: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.020,
longitudeDelta: 0.020,
}
}, () => this.getLocations());
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 },
);
}
getLocations() {
return fetch('http://media-panda.de/bp/whs.geojson')
.then(response => response.json())
.then(responseData => {
let { region } = this.state;
let { latitude, longitude } = region;
let markers = responseData.features.map(feature => {
let coords = feature.geometry.coordinates
return {
coordinate: {
latitude: coords[1],
longitude: coords[0],
}
}
}).filter(marker => {
let distance = this.calculateDistance(latitude, longitude, marker.coordinate.latitude, marker.coordinate.longitude);
return distance <= 500;
});
this.setState({
markers: markers,
loaded: true,
});
}).done();
}
calculateDistance(origLat, origLon, markerLat, markerLon) {
return geolib.getDistance(
{latitude: origLat, longitude: origLon},
{latitude: markerLat, longitude: markerLon}
);
}
render() {
return (
<View style={styles.container}>
<MapView.Animated
style={styles.map}
region={this.state.region}
showsUserLocation={true}
>
{this.state.markers.map(marker => (
<MapView.Marker
coordinate={marker.coordinate}
/>
))}
<MapView.Circle
key = { (this.state.latitude + this.state.longitude).toString() }
center = { this.state.region }
radius = { 500 }
strokeWidth = { 1 }
strokeColor = { '#1a66ff' }
fillColor = { 'rgba(230,238,255,0.5)' }
/>
</MapView.Animated>
</View>
);
}
}
export default Grillplaetze;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
},
map: {
width: "100%",
height: "100%",
},
})
Your errors aren't related to your implementation of the geolib but instead they are due to your implementation of the MapView.Circle.
If we look at the documentation the MapView.Circle we see the following:
| Prop | Type | Default | Note |
|----------|----------|------------|------------------------------------------------|
| `center` | `LatLng` | (Required) | The coordinate of the center of the circle .
| `radius` | `Number` | (Required) | The radius of the circle to be drawn (in meters)
Both the center and the radius are required fields.
If we look at your code:
<MapView.Circle
key = { (this.state.latitude + this.state.longitude).toString() }
center = { this.state.region }
radius = { 500 }
strokeWidth = { 1 }
strokeColor = { '#1a66ff' }
fillColor = { 'rgba(230,238,255,0.5)' }
/>
It would appear that you have set them, however you have not actually set the region. You can confirm this by checking your initial state.
constructor () {
super();
this.state = {
markers: [],
loaded: false
}
}
Notice that you have not set an initial region for the map. This is what is causing your error. The app is trying to handle the undefined value for the region.
To overcome this the easiest way is to set an initial region for the map in state.
Something like this:
constructor () {
super();
this.state = {
markers: [],
loaded: false,
region: {
latitude: 0,
longitude: 0,
latitudeDelta: 0.020,
longitudeDelta: 0.020
},
latitude: 1,
longitude: 1
};
}
If you app is for a specific region then it may make sense to pick an initial region that is close to where you app is going to be used.
Also note in your MapView.Circle code you are also using undefined values of latitude and longitude for the key. I don't think that you need to define a key property for the MapView.Circle. I cannot find any mention of this being a requirement in the documentation.
Making the above changes allows the code to work.
Some other points.
You are importing geolib twice. You only need to do it once. You should either have import GeoLib from 'geolib'; or const geolib = require('geolib'); you don't need both. Seeing as you are using geolib with a lower case, I would just remove import GeoLib from 'geolib';
You are importing Markers from react-native-maps in the wrong way. It should be imported as import { Markers } from 'react-native-maps, however you are using the Markers as MapView.Markers which is absolutely fin. I think you can remove the unused and incorrect import Markers from 'react-native-maps
MapView.Animated I am not 100% that this is correct or required. I haven't seen it used in this way before. However if it is not causing you issues then I suppose it isn't really a problem.
You should also add a key prop on your Markers so that you suppress the warning that it is missing. This should be something unique.