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

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

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 };
}

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.

MapboxGL React Native UserLocation Indicator do not display on map

The UserIndicator from <MapboxGL.UserLocation>, work and display fine on IOS, but with android, it's depends, it sometime work, sometime not, and i realize also, that my CameraRef.current.setCamera() is undefined when the UserIndicator doesn't display.
I tried to request with all the way i could, the location permissions like this :
React Native :
PermissionsAndroid.requestMultiple(
[PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION],
{
title: 'Give Location Permission',
message: 'App needs location permission to find your position.'
}
).then((res) => console.log(res))
MapboxGL :
if (Platform.OS == "android") {
var temp = await MapboxGL.requestAndroidLocationPermissions()
}
expo :
let { status } = await Location.requestPermissionsAsync();
all this request permissions work fine and have a output "granted" or granted : true
this is my map Component :
var Map = ({ navigation }) => {
const MapRef = React.useRef(null)
const CameraRef = React.useRef(null)
const LocationRef = React.useRef(null)
const { user, setUser } = React.useContext(UserContext)
const [data, setDATA] = React.useState([null])
const [reload, setReload] = React.useState(false)
const {location, setLocation} = React.useContext(LocationContext)
console.log(location)
var test = null;
React.useEffect(() => {
MapboxGL.setTelemetryEnabled(false);
MapboxGL.locationManager.start();
return () => {
MapboxGL.locationManager.stop();
}
// console.log(LocationRef.current)
}, [])
function handleClick() {
CameraRef.current.setCamera({
centerCoordinate: [location.coords.longitude, location.coords.latitude],
zoomLevel: 11,
animationDuration: 200,
})
}
function CenterCamera() {
if (CameraRef.current) {
CameraRef.current.setCamera({
centerCoordinate: [location.coords.longitude, location.coords.latitude],
zoomLevel: 11,
animationDuration: 2000,
})
}
}
function goTo(latitude, longitude) {
CameraRef.current.setCamera({
centerCoordinate: [longitude, latitude],
zoomLevel: 13,
animationDuration: 100,
})
}
function DisplayPings(data) {
if (data.data.length > 0) {
if (data.data[0].type_id == null) {
data.data[0].type_id = 1;
}
const val = searchInJson(data.data[0].type_id)
const features = setFeatures(val, data.data[0])
return (
<View key={data.data[0].id_activity_data}>
<MapboxGL.Images
images={{
FootBall: json[0].url,
}}
/>
<MapboxGL.ShapeSource hitbox={{ width: 20, height: 20 }} onPress={() => goTo(data.data[0].latitude, data.data[0].longitude)} id={(data.data[0].id_activity_data).toString()} shape={features}>
<MapboxGL.SymbolLayer id={(data.data[0].id_activity_data).toString()} style={{ iconImage: ['get', 'icon'] }} />
</MapboxGL.ShapeSource>
</View>
);
}
}
if (location && location.city != null && data.data) {
return (
<View style={styles.page}>
<MapboxGL.MapView onPress={() => console.log("test")} ref={(ref) => {
}
} style={styles.map} compassEnabled={false} zoomEnabled={true} >
<MapboxGL.UserLocation />
<MapboxGL.Camera ref={(ref) => {
CameraRef.current = ref
CenterCamera()
}} />
{data.data.map((data) => DisplayPings(data))}
</MapboxGL.MapView>
<ComponentsOnmap></ComponentsOnmap>
<TouchableOpacity style={styles.rondLocation} onPress={handleClick}>
<FontAwesome5 name="location-arrow" size={24} color="#434040" />
</TouchableOpacity>
<BottomSheet city={location.city} data = {data} setReload = {setReload} navigation={navigation}></BottomSheet>
</View>)
}
else
return (
<View style={styles.page}>
<MapboxGL.MapView ref={MapRef} compassEnabled={false} style={styles.map} zoomEnabled={true} >
<MapboxGL.UserLocation ref={LocationRef} />
</MapboxGL.MapView>
<ComponentsOnmap></ComponentsOnmap>
<BottomSheet city="No location" navigation={navigation}></BottomSheet>
</View>
)
}
export default Map
My condition location && location.city != null works fine, i tried without it, but the problem is still the same
My Location Context :
import React, { Component, createContext, useState, useContext } from "react";
import { Platform, PermissionsAndroid } from "react-native"
import * as Location from 'expo-location';
import MapboxGL from "#react-native-mapbox-gl/maps";
import { GetLocation } from "../API/GetLocation"
export const LocationContext = createContext();
MapboxGL.setAccessToken("Je l'ai caché bande de petit malin");
export default LocationProvider = ({ children }) => {
const [location, setLocation] = useState({ coords: [], city: null, permission: false })
const [city, SetCity] = React.useState(null)
const [coords, setCoords] = React.useState([])
React.useEffect(() => {
PermissionsAndroid.requestMultiple(
[PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION],
{
title: 'Give Location Permission',
message: 'App needs location permission to find your position.'
}
).then((res) => console.log(res))
GetLocation.then((res) => {
setLocation(res)
})
}, [])
return (
<LocationContext.Provider value={{ location, setLocation, city, SetCity, coords, setCoords }}>
{children}
</LocationContext.Provider>
)
}
My GetLocation Promise
import { useContext } from "react"
import { Platform } from "react-native"
import * as Location from 'expo-location';
import MapboxGL from "#react-native-mapbox-gl/maps";
export const GetLocation = new Promise(async (resolve, reject) => {
if (Platform.OS == "android") {
var temp = await MapboxGL.requestAndroidLocationPermissions()
}
let { status } = await Location.requestPermissionsAsync();
if (status == "granted")
Location.getCurrentPositionAsync().then((location) => {
console.log(location)
console.log("ca marche ap")
let longitude = location.coords.longitude
let latitude = location.coords.latitude
return ({ latitude, longitude })
}).then(async (coords) => Location.reverseGeocodeAsync(coords).then(async (adress) => {
resolve({ coords: coords, city: adress[0].city, granted: true })
})).catch((error) => console.log(reject(error)));
})

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

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.