react native maps onPress marker drop problem - react-native

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: ...
}
}

Related

Markers don't always show up in the MapView of the Map page of my react-native app

There are 4 "parceiros" (partners) registered in the database. Each partner has an address, in the model "Street Ocean View, 182". These addresses are converted to coordinates in the useCoordinates hook. But markers don't always load on the map. I searched for a solution but hard to find someone who has done the same in react-native > 0.69
/src/page/mapa/index.js
import { useState, useEffect } from 'react';
import { View, PermissionsAndroid, Image } from 'react-native';
import BarraPesquisa from '../../components/BarraPesquisa';
import MapView, { Marker } from 'react-native-maps';
import Geolocation from "react-native-geolocation-service";
import useCoordenadas from '../../hooks/useCoordenadas';
import { useNavigation } from '#react-navigation/native';
import markerIcon from '../../assets/images/marker.png';
import { estilos } from './estilos';
export default function Mapa() {
const {coordenadas, carregaCoordenadas} = useCoordenadas();
const [localizacaoAtual, setLocalizacaoAtual] = useState({});
const [permiteGPS, setPermiteGPS] = useState(false);
const [mapReady, setMapReady] = useState(false);
const navigation = useNavigation();
const geolocation = Geolocation;
const requestLocationPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Geolocation Permission',
message: 'Can we access your location?',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === 'granted') {
console.log('Permissão para acesso à geolocalização concedida')
setPermiteGPS(true);
return true;
} else {
console.log('Permissão para acesso à geolocalização não concedida');
return false;
}
} catch (err) {
return false;
}
};
useEffect( () => {
carregaCoordenadas();
requestLocationPermission();
}, [])
useEffect( () => {
permiteGPS && geolocation.getCurrentPosition(
position => {
setLocalizacaoAtual({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
coordinates: {
latitude: position.coords.latitude,
longitude: position.coords.longitude
}
});
},
error => {
console.log(error.message.toString());
},
{
showLocationDialog: true,
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 0
}
);
}, [permiteGPS])
useEffect(() => {
},[coordenadas])
return (
<View>
<BarraPesquisa style={estilos.searchSection} />
{ ( localizacaoAtual !== undefined &&
localizacaoAtual.hasOwnProperty('latitude') &&
localizacaoAtual.hasOwnProperty('longitude')) &&
<MapView
onMapReady={() => setTimeout(() => setMapReady(true), 10000)}
loadingEnabled = {true}
provider="google"
style={estilos.map}
initialRegion={{
latitude: localizacaoAtual.latitude,
longitude: localizacaoAtual.longitude,
latitudeDelta: 0.04,
longitudeDelta: 0.05,
}}
>
{ coordenadas && coordenadas.map((coordenada, i) => {
return (
<Marker
key={i}
tracksViewChanges={!mapReady}
coordinate={{"latitude": coordenada.lat, "longitude": coordenada.lng}}
pinColor={"orange"}
onPress={() => {
navigation.navigate('ParceiroDetalhes', coordenada.detalhes) }}>
<Image source={markerIcon} style={{height: 35, width: 35}}/>
</Marker>
)
})
}
</MapView>
}
</View>
)
}
/src/hooks/useCoordenadas.js
import { useState } from 'react';
import { listaParceiros } from '../services/requisicoes/parceiros';
import Geocode from "react-geocode";
export default function useCoordenadas() {
const [ coordenadas, setCoordenadas ] = useState([]);
const carregaCoordenadas = async () => {
const parceiros = await listaParceiros();
let coordenadasArray = [];
Geocode.setApiKey("MY_API_KEY");
Geocode.setRegion("br");
Geocode.setLanguage("cs");
Geocode.enableDebug(true);
Promise.all(
parceiros.map((parceiro) => {
Geocode.fromAddress(parceiro.Endereco).then(
(response) => {
const location = response.results[0].geometry.location;
if(location.hasOwnProperty('lat') && location.hasOwnProperty('lng')){
coordenadasArray.push({
detalhes: parceiro,
lat: location.lat,
lng: location.lng,
});
}
},
(error) => {
console.error(error);
}
)
})).then(() => {
setCoordenadas(coordenadasArray)
}
)
}
return { coordenadas, carregaCoordenadas };
}

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.,

Performance Issue with react-native-map-clustering

Im loading some markers from the Overpass API (OpenStreetMap) and showing them in a ClusterMap. Although Markers are clustered now, the App has a bad performace and high interactivity latency. Is it possible to get better interactivity?
Expo: https://expo.dev/#ezcodeezlife/markercluster-test
Code:
import { ActivityIndicator, FlatList, Text, View, StyleSheet } from 'react-native';
import { Marker } from 'react-native-maps';
import { ClusterMap, AnimatedRegion } from 'react-native-cluster-map';
//This function was provided here: https://github.com/react-native-maps/react-native-maps/issues/356#issuecomment-515694070
export const getBoundByRegion = (region, scale = 1) => {
}
export default App = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [region, setRegion] = useState({
latitude: 50.22364,
longitude: 8.4491,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
});
const getBenches = async () => {
try {
const response = await fetch('https://overpass.openstreetmap.fr/api/interpreter?data=[out:json];(node[%27amenity%27=%27bench%27](50.22364307664712,8.449115594560567,50.24036141038248,8.46567765838438);node[%27leisure%27=%27picnic_table%27](50.22364307664712,8.449115594560567,50.24036141038248,8.46567765838438););out%20body;');
const json = await response.json();
setData(json);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
const getNewBenches = async (bounds) => {
try {
const response = await fetch("https://overpass.openstreetmap.fr/api/interpreter?data=[out:json];node[%27amenity%27=%27bench%27](" + bounds.minLat +"," + bounds.minLng + "," + bounds.maxLat + "," + bounds.maxLng + ");out%20body;");
const json = await response.json();
setData(json);
} catch (error) {
console.error(error);
} finally {
}
}
useEffect(() => {
getBenches();
}, []);
if(isLoading == false) {
return (
<>
<View>
<ClusterMap
style={styles.container}
region={ region }
mapType={"satellite"}
onRegionChangeComplete={(region) => {
setRegion(region);
getNewBenches(getBoundByRegion(region));
} }
//onMapReady={() => onMapReady()}
>
{data.elements.map((marker) => (
<Marker
tracksViewChanges={false}
key={marker.id}
coordinate={{ latitude: marker.lat, longitude: marker.lon }}
/>
))}
</ClusterMap >
</View>
</>
)
} else {
return (
<View>
<ActivityIndicator />
</View>
)
}
};
//styles
Is it possible to get better interactivity?
I had a similar issue and it was because I left many console logs in the code. after I removed them, my map interactivity was much much better. Try to remove as many unnecessary console logs as possible.

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;

React Native Maps - Null Object Reference

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" />