I use DefaultMarkers to get location from user.
I have a button and a function. In the function I use a code to show latitude in console. Now When I press the button, in console not happening but for second press I can see latitude in console.
If I change location and try again, I should press button for twice to see latitude in console.
constructor(props){
super(props);
this.state={
markers: [],
}
}
onMapPress(e) {
this.setState({
markers: [
{
coordinate: e.nativeEvent.coordinate,
key: 0,
},
],
});
}
SaveAddress=()=>{
console.log(JSON.stringify(this.state.markers[0].coordinate.latitude);
}
<Button onPress={this.SaveAddress}>
<Text>Save</Text>
</Button>
<MapView
style={styles.map}
initialRegion={{
latitude: 28.95761453,
longitude: 50.83710976,
latitudeDelta: 0.0040,
longitudeDelta: 0.0040,
}}
provider={this.props.provider}
onPress={(e) => this.onMapPress(e)}
>
{this.state.markers.map(marker => (
<Marker
key={marker.key}
coordinate={marker.coordinate}
/>
))}
</MapView>
Because, when you first-time press that button to execute this function
SaveAddress=()=>{console.log(JSON.stringify(this.state.markers[0].coordinate.latitude);}
The state is empty so you don't get any value. On your first press, it just starts to save the state and start to render. But on your second press, rendering is complete and the states became set then you got the value.
You can do instead
import React, { Component } from 'react';
import { View, Text, TouchableOpacity, WebView, StyleSheet,KeyboardAvoidingView, ActivityIndicator,Platform,TextInput,Dimensions} from 'react-native'
import MapView, { PROVIDER_GOOGLE, Region,Marker } from 'react-native-maps';
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
markers: [
{
coordinate: { latitude: 28.95761453,
longitude: 50.83710976,
},
key: 0,
},
],
}
}
onMapPress(e) {
this.setState({
markers: [
{
coordinate: e.nativeEvent.coordinate,
key: 0,
},
],
});
}
SaveAddress=()=>{
console.log(JSON.stringify(this.state.markers[0].coordinate.latitude))
}
render() {
return (
<View style={{flex:1}}>
<MapView
style={[styles.map]}
initialRegion={{
latitude: 28.95761453,
longitude: 50.83710976,
latitudeDelta: 0.0040,
longitudeDelta: 0.0040,
}}
// onMapReady={this.onMapReady}
provider={ PROVIDER_GOOGLE}
onPress={(e) => this.onMapPress(e)}
>
{this.state.markers.map(marker => (
<Marker
key={marker.key}
coordinate={marker.coordinate}
/>
))}
</MapView>
<TouchableOpacity onPress={()=>this.SaveAddress()}>
<Text>Save</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
map: {
...StyleSheet.absoluteFillObject,
},
});
Related
markersArr - an array of objects containing the title, latitude, and longitude:
Array [
Object {
"latitude": 31.74972996282075,
"longitude": 35.23612361202195,
"title": "ארמון הנציב",
},
Object {
"latitude": 31.779044392761453,
"longitude": 35.18955094821394,
"title": "בית הכרם",
},
Object {
"latitude": 31.765429951578884,
"longitude": 35.231964301905144,
"title": "אבו תור",
},
Object {
"latitude": 31.748258119122376,
"longitude": 35.21971512763567,
"title": "ארנונה",
},
]
The hardcoded Marker shows but the other doesn't and I can't figure out why.
The data in the array is correct.
This is the return statement:
return (
<SafeAreaView style={globalStyles.mapScreenContainer}>
<MapView
style={globalStyles.map}
region={mapRegion}
provider={null}
onMarkerPress={(e) => handleMarkerPressed(e)}
>
<Marker
coordinate={{ latitude: 31.7851951925, longitude: 35.2060641757 }}
pinColor={"purple"}
title={"מרכז מאי"}
description={"מיקום העמותה"}
onPress={() => {
console.log("");
}}
/>
{markersArr.map((marker) => {
console.log(marker);
<Marker
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
pinColor={"purple"}
title={marker.title}
onPress={() => {
handleMarkerPressed();
}}
/>;
})}
</MapView>
</SafeAreaView>
);
and the whole component if necessary:
import React, { useState, useEffect, Component } from "react";
import MapView, { Marker } from "react-native-maps";
import { SafeAreaView } from "react-native-safe-area-context";
import { globalStyles } from "../../styles/global";
import { useData } from "../../AuthProvider/UserDataProvider";
const MapScreen = () => {
const { markers, getMarkers } = useData();
const [markersArr, setMarkersArr] = useState([]);
const [mapRegion, setmapRegion] = useState({
latitude: 31.7851951925,
longitude: 35.2060641757,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
});
const handleMarkerPressed = (event) => {
// console.log(event.nativeEvent);
};
useEffect(() => {
getMarkers().then(() => {
for (const marker in markers) {
if (markers.hasOwnProperty.call(markers, marker)) {
setMarkersArr((prev) => [
...prev,
{
title: marker,
latitude: markers[marker].latitude,
longitude: markers[marker].longitude,
},
]);
}
}
});
return () => {};
}, []);
return (
<SafeAreaView style={globalStyles.mapScreenContainer}>
<MapView
style={globalStyles.map}
region={mapRegion}
provider={null}
onMarkerPress={(e) => handleMarkerPressed(e)}
>
<Marker
coordinate={{ latitude: 31.7851951925, longitude: 35.2060641757 }}
pinColor={"purple"}
title={"מרכז מאי"}
description={"מיקום העמותה"}
onPress={() => {
console.log("");
}}
/>
{markersArr.map((marker) => {
console.log(marker);
<Marker
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
pinColor={"purple"}
title={marker.title}
onPress={() => {
handleMarkerPressed();
}}
/>;
})}
</MapView>
</SafeAreaView>
);
};
export default MapScreen;
I get no errors when rendering the map
I've forgotten the return inside the map, added it and now it's working
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 am doing a RN project using Geolocation to get the current location, but I don't know what's wrong in this.
Here is my code:
import React, { Component } from 'react';
// Import required component
import { SafeAreaView, StyleSheet, Text, Alert, TouchableOpacity, Image, View } from 'react-native';
import { request, PERMISSIONS } from 'react-native-permissions';
// Import vector icons
import Icon from 'react-native-vector-icons/FontAwesome';
import MapView, { PROVIDER_GOOGLE, Platform, Marker, Callout, Circle } from 'react-native-maps';
import coordinate from '../../api/binLocationData';
import Geolocation from '#react-native-community/geolocation';
export class Home extends Component {
componentDidMount() {
this.requestLocationPermission();
}
requestLocationPermission = async () => {
if (Platform.OS === 'IOS') {
var response = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);
console.log('IOS: ' + response);
if (response === 'granted') {
this.locateCurrentPosition();
}
} else {
var response = await request(PERMISSIONS.ANDROID.LOCATION_WHEN_IN_USE);
console.log('Android: ' + response);
if (response === 'granted') {
this.locateCurrentPosition();
}
}
};
locateCurrentPosition = () => {
Geolocation.getCurrentPosition(
(position) => {
console.log(JSON.stringify(position));
let initialPosition = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
};
this.setState({ initialPosition });
},
(error) => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 1000, maximumAge: 1000 },
);
};
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
ref={(map) => (this._map = map)}
showsUserLocation={true}
style={styles.maps}
initialRegion={this.state.initialPosition}
// initialRegion={{
// latitude: 16.0599,
// longitude: 108.2438,
// latitudeDelta: 0.05,
// longitudeDelta: 0.05,
// }}
>
<Circle
radius={1000}
center={{ latitude: 16.0599, longitude: 108.2438 }}
fillColor={'rgba(51,150,152,0.3)'}
/>
<Marker coordinate={{ latitude: 16.0599, longitude: 108.2438 }}>
<Callout>
<Text>Bin 1</Text>
</Callout>
{/* <Image source={require('./src/assets/icons/bin.png')} /> */}
</Marker>
{coordinate.map((marker) => (
<Marker
key={marker.id}
coordinate={{ latitude: marker.latitude, longitude: marker.longitude }}
title={marker.name}
/>
))}
</MapView>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
maps: {
...StyleSheet.absoluteFillObject,
},
});
export default Home;
And the debugging show:
TypeError: null is not an object (evaluating 'this.state.initialPosition')
How can I fix it?
You forget to initialise state. You should add this to your class component:
constructor(props) {
this.state = {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0,
};
}
This should works:
import React, { Component } from "react";
// Import required component
import {
SafeAreaView,
StyleSheet,
Text,
Alert,
TouchableOpacity,
Image,
View,
} from "react-native";
import { request, PERMISSIONS } from "react-native-permissions";
// Import vector icons
import Icon from "react-native-vector-icons/FontAwesome";
import MapView, {
PROVIDER_GOOGLE,
Platform,
Marker,
Callout,
Circle,
} from "react-native-maps";
import coordinate from "../../api/binLocationData";
import Geolocation from "#react-native-community/geolocation";
export class Home extends Component {
constructor(props) {
this.state = {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0,
};
}
componentDidMount() {
this.requestLocationPermission();
}
requestLocationPermission = async () => {
if (Platform.OS === "IOS") {
var response = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);
console.log("IOS: " + response);
if (response === "granted") {
this.locateCurrentPosition();
}
} else {
var response = await request(PERMISSIONS.ANDROID.LOCATION_WHEN_IN_USE);
console.log("Android: " + response);
if (response === "granted") {
this.locateCurrentPosition();
}
}
};
locateCurrentPosition = () => {
Geolocation.getCurrentPosition(
(position) => {
console.log(JSON.stringify(position));
let initialPosition = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
};
this.setState({
latitude: initialPosition.latitude,
longitude: initialPosition.longitude,
latitudeDelta: initialPosition.latitudeDelta,
longitudeDelta: initialPosition.longitudeDelta,
});
},
(error) => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 1000, maximumAge: 1000 }
);
};
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
ref={(map) => (this._map = map)}
showsUserLocation={true}
style={styles.maps}
initialRegion={this.state.initialPosition}
// initialRegion={{
// latitude: 16.0599,
// longitude: 108.2438,
// latitudeDelta: 0.05,
// longitudeDelta: 0.05,
// }}
>
<Circle
radius={1000}
center={{ latitude: 16.0599, longitude: 108.2438 }}
fillColor={"rgba(51,150,152,0.3)"}
/>
<Marker coordinate={{ latitude: 16.0599, longitude: 108.2438 }}>
<Callout>
<Text>Bin 1</Text>
</Callout>
{/* <Image source={require('./src/assets/icons/bin.png')} /> */}
</Marker>
{coordinate.map((marker) => (
<Marker
key={marker.id}
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
title={marker.name}
/>
))}
</MapView>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
maps: {
...StyleSheet.absoluteFillObject,
},
});
export default Home;
Unable to drag the map around, after using google auto complete to search for the location. The map is able to change to the location. However I am unable to drag the map around, its stuck to the center of the location that I searched.
MapContainer.js is used to render the map and componentdidmount is used to retrieve the coordinates of busstops which will be displayed as markers under the render below
import { View } from "react-native";
import MapInput from "./MapInput";
import { getLocation, geocodeLocationByName } from "./location-service";
import React, { Component } from "react";
import MapView, { Marker, StyleSheet } from "react-native-maps";
const MyMapView = (props) => {
return (
<MapView
style={{ flex: 1 }}
region={props.region}
showsUserLocation={true}
onRegionChange={(reg) => props.onRegionChange(reg)}
>
{props.busstopArray.map((item) => {
return (
<Marker
key={item.bus_stop_id}
coordinate={{
latitude: Number(item.latitude),
longitude: Number(item.longitude),
}}
title={item.name}
></Marker>
);
})}
</MapView>
);
};
class MapContainer extends React.Component {
state = {
region: {},
busstop: [], //busstop is an empty array, in which the JSON values will be added, to be used later in the code.
};
componentDidMount() {
this.getInitialState();
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ route_id: "1" }, { route_id: "2" }),
};
fetch(
"https://laravelsyd-fypfinalver.herokuapp.com/getBusStop",
requestOptions
)
.then((response) => response.json())
.then((data) => {
this.setState({ busstop: data });
});
}
getInitialState() {
getLocation().then((data) => {
//import locationservice
console.log(data); //prints out intial region coords
this.setState({
region: {
latitude: data.latitude,
longitude: data.longitude,
latitudeDelta: 0.003,
longitudeDelta: 0.003,
},
});
});
}
getCoordsFromName(loc) {
this.setState({
region: {
latitude: loc.lat,
longitude: loc.lng,
latitudeDelta: 0.003,
longitudeDelta: 0.003,
},
});
}
onMapRegionChange(region) {
this.setState({ region });
}
render() {
const bus_stop = [...this.state.busstop];
// console.log(bus_stop); //testing to see if can display the json objects and it can
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapInput notifyChange={(loc) => this.getCoordsFromName(loc)} />
</View>
{this.state.region["latitude"] ? (
<View style={{ flex: 1 }}>
<MyMapView
region={this.state.region}
onRegionChange={(reg) => this.onMapRegionChange(reg)}
busstopArray={bus_stop}
/>
</View>
) : null}
</View>
);
}
}
export default MapContainer;
you have to add draggable in Marker:
<Marker
draggable
coordinate={{
latitude: Number(this.state.location.latitude),
longitude: Number(this.state.location.longitude),
}}
onDragEnd={e =>
this.setState({location: e.nativeEvent.coordinate})
}
/>
I feel I've tried every combination of onPress events and function calls but nothing works. I am too noob to see what the issue is. Is it because it's rested in a few return statements?
I've ellipse'd code that isn't relevant. It works fine but the button will appear to not do anything. No errors or anything.
Thanks
import React from 'react';
import {
...
Button,
} from 'react-native';
//Import other react maps stuff
......
const dest = {latitude: -37.836037, longitude: 145.036730};
const waypoint = [
{address: '123 Fake St, Anglesea', latitude: -37.861738, longitude: 145.002500},
{address: '321 Real St, Anglesea', latitude: -37.806694, longitude: 145.010026}
];
class TodaysJobs extends React.Component {
state = {
location: null,
errorMessage: null,
};
//Get user current location
componentWillMount() {
....
}
_getLocationAsync = async () => {
....
};
moveMap() {
alert('Simple Button pressed');
const coordinate = waypoint[0];
this.map.animateToRegion({
latitude: -37.223423,
longitude: 145.423442,
latitudeDelta: 0.1,
longitudeDelta: 0.1
},
350
);
}
render() {
if (this.state.loaded) {
// if we have an error message show it
if (this.state.errorMessage) {
return (
....
);
} else if (this.state.location) {
// if we have a location show it
return (
<View style={{ flex: 1 }}>
<MapView
ref={(ref) => { this.mapRef = ref }}
style={ styles.mapStyle }
region={{
latitude: this.state.location.coords.latitude,
longitude: this.state.location.coords.longitude,
latitudeDelta: 0.1,
longitudeDelta: 0.1
}}
>
{waypoint.map(function(item, i){
return <MapView.Marker
key={i}
coordinate={item}
/>
})}
<MapViewDirections
origin={this.state.location.coords}
waypoints={waypoint}
destination={dest}
/>
</MapView>
<ScrollView style={ styles.mapStyle }>
{waypoint.map(function(item, i){
return (
<View key={i} style={ styles.houseList }>
<Text>{item.address}</Text>
<Button
title={item.address}
onPress={this.moveMap}
/>
</View>
);
})}
</ScrollView >
</View>
);
}
} else {
// if we haven't loaded show a waiting placeholder
return (
<View>
<Text>Waiting...</Text>
</View>
);
}
}
}
export default TodaysJobs;
//Styles
....
You are using waypoint.map(function(item, i) and then onPress={this.moveMap}. this is defined in runtime and so this.moveMap will be undefined.
Try using fat arrow function instead of native function.
{
waypoint.map((item, i) => {
return (
<View key={i} style={styles.houseList}>
<Text>{item.address}</Text>
<Button
title={item.address}
onPress={this.moveMap}
/>
</View>
);
})
}
if you want to read more about the difference read this blog