I want to get the directions from 2 points (origin and destination)
i have written a simple function to get longitude and latitude.
it looks like this
const GetLongitudeFromAddress = (address) =>{
var logLatApi = 'https://maps.googleapis.com/maps/api/geocode/json?address='+address+'&sensor=false&key=AIzaSyBsy6x3mTXbPQ52qk6XMI9u1NgMfn9-YNE';
var header = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
fetch(
logLatApi,{
method : 'GET',
headers : header
}
).then((response) => response.json())
.then((responseJson)=>{
if(responseJson.status ==='OK')
{
this.setState({longitude: responseJson.results[0].geometry.location.lng});
this.setState({latitude: responseJson.results[0].geometry.location.lat});
}
})
}
Now i want to use it in inputText Like this
<TextInput
style={styles.input}
placeholder="Origin"
onChangeText={text => GetLongitudeFromAddress(text)}
/>
it does not seem to work, i get this As error possible promised handled rejection which looks like this image below
How can I use this with useState? My code is looking like this below :
import React , {useState, useEffect} from 'react';
import {StyleSheet, View, Dimensions, TextInput} from 'react-native';
import MapView , { Marker , Polyline } from 'react-native-maps';
import MapViewDirections from 'react-native-maps-directions';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
const ShowMap =() =>{
const GetLongitudeFromAddress = (address) =>{
var logLatApi = 'https://maps.googleapis.com/maps/api/geocode/json?address='+address+'&sensor=false&key=AIzaSyBsy6x3mTXbPQ52qk6XMI9u1NgMfn9-YNE';
var header = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
fetch(
logLatApi,{
method : 'GET',
headers : header
}
).then((response) => response.json())
.then((responseJson)=>{
if(responseJson.status ==='OK')
{
this.setState({longitude: responseJson.results[0].geometry.location.lng});
this.setState({latitude: responseJson.results[0].geometry.location.lat});
}
})
}
const [coordinates] = useState([
{
latitude: 6.450430,
longitude: 3.390460,
},
{
latitude: 6.430980,
longitude: 3.435880,
},
]);
return(
<View style={styles.container}>
<MapView
style={styles.maps}
initialRegion={{
latitude: coordinates[0].latitude,
longitude: coordinates[0].longitude,
latitudeDelta: 0.0622,
longitudeDelta: 0.0121,
}}>
<MapViewDirections
origin={coordinates[0]}
destination={coordinates[1]}
apikey="AIzaSyBsy6x3mTXbPQ52qk6XMI9u1NgMfn9-YNE"
strokeWidth={4}
strokeColor="#FD0631"
/>
<Marker coordinate={coordinates[0]} />
<Marker coordinate={coordinates[1]} />
</MapView>
<View style={styles.inputView}>
<TextInput
style={styles.input}
placeholder="Origin"
onChangeText={text => GetLongitudeFromAddress(text)}
/>
<TextInput
style={styles.input}
placeholder="Destination"
onChangeText={text => GetLongitudeFromAddress(text)}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
maps: {
width: Dimensions.get('screen').width,
height: Dimensions.get('screen').height,
},
inputView:{
backgroundColor: 'rgba(0,0,0,0)',
position: 'absolute',
top: 0,
left: 5,
right: 5
},
input: {
height: 50,
padding: 10,
marginTop: 20,
marginLeft: 10,
marginRight: 10,
fontSize: 18,
borderWidth: 1,
borderRadius: 35,
borderColor: '#EEEEEE',
backgroundColor: 'white',
}
});
export default ShowMap;
How do i go about this? How Can I use this GetLongitudeFromAddress to get the longitude and latitude from both feilds. Kindly assist
You need to have a button that will call the function GetLongitudeFromAddress when pressed. Calling this function every change of your input text value will be costly as it will call geocoding requests everytime the function is called.
I successfully modified your code to get the address from the input text then convert it using the function, then use the converted coordinates as input to MapViewDirections. Here's a sample code and a code snippet below with inline comments:
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Dimensions, TextInput, Button } from 'react-native';
import MapView, { Marker, Polyline } from 'react-native-maps';
import MapViewDirections from 'react-native-maps-directions';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
const { width, height } = Dimensions.get('window');
const ShowMap = () => {
//initial maps coordinate
const [initialCenter] = useState({
latitude: 6.45043,
longitude: 3.39046,
});
//state variables for the value of the textbox
const [originInput, setOInput] = useState(null);
const [destInput, setDInput] = useState(null);
//state variables to handle the coordinates after getting it from GetLongitudeFromAddress function
const [originReq, setOReq] = useState(null);
const [destReq, setDReq] = useState(null);
//state variable that will be one of the condition to trigger MapViewDirections once button is pressed
const [isBtnPressed, setBtn] = useState(null);
//state variable that will be a condition to show the origin and destination marker once the route was started
const [routeStarted, setRouteStarted] = useState(null);
//function that will convert the address from your inpput textbox to a coordinate(geocoding)
//coord variable will be the variable that will determine if you are converting the origin or the destination coordinates
const GetLongitudeFromAddress = (address, coord) => {
var logLatApi =
'https://maps.googleapis.com/maps/api/geocode/json?address=' +
address +
'&sensor=false&key=YOUR_KEY';
var header = {
Accept: 'application/json',
'Content-Type': 'application/json',
};
fetch(logLatApi, {
method: 'GET',
headers: header,
})
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.status === 'OK') {
//check if coord value is 'origin' or destination'
if (coord == 'origin' || coord == 'destination') {
if (coord == 'origin') {
//if origin, it will change the originReq state value to the result
setOReq({
latitude: responseJson.results[0].geometry.location.lat,
longitude: responseJson.results[0].geometry.location.lng,
});
} else {
//if destination, it will change the destReq state value to the result
setDReq({
latitude: responseJson.results[0].geometry.location.lat,
longitude: responseJson.results[0].geometry.location.lng,
});
}
}
}
});
};
//function called when the button is pressed
const processAddress = () => {
//it will pass the current value of your input state and hardcoding origin or destination to mark if the address being converted to coordinates is either one of them
GetLongitudeFromAddress(originInput, 'origin');
GetLongitudeFromAddress(destInput, 'destination');
//change isBtnPressed state variable value
setBtn('Y');
};
//function called when the route is ready, it will also fit the polyline to the current view
const routeReady = (result) => {
console.log(`Distance: ${result.distance} km`);
console.log(`Duration: ${result.duration} min.`);
console.log(isBtnPressed);
this.mapView.fitToCoordinates(result.coordinates, {
edgePadding: {
right: width / 20,
bottom: height / 20,
left: width / 20,
top: height / 20,
},
});
};
return (
<View style={styles.container}>
<MapView
style={styles.maps}
ref={(c) => (this.mapView = c)}
initialRegion={{
latitude: initialCenter.latitude,
longitude: initialCenter.longitude,
latitudeDelta: 0.0622,
longitudeDelta: 0.0121,
}}>
{isBtnPressed !== null && originReq !== null && destReq !== null && (
<MapViewDirections
origin={originReq}
destination={destReq}
apikey="YOUR_KEY"
strokeWidth={4}
strokeColor="#FD0631"
onStart={() => {
setRouteStarted('Y');
}}
onReady={(result) => {
routeReady(result);
}}
onError={() => {
setRouteStarted(null);
}}
/>
)}
{routeStarted !== null && originReq != null && (
<Marker coordinate={originReq} />
)}
{routeStarted !== null && destReq != null && (
<Marker coordinate={destReq} />
)}
</MapView>
<View style={styles.inputView}>
<TextInput
style={styles.input}
placeholder="Origin"
onChangeText={(text) => setOInput(text)}
/>
<TextInput
style={styles.input}
placeholder="Destination"
onChangeText={(text) => setDInput(text)}
/>
<Button title="Press me" color="#f194ff" onPress={processAddress} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
maps: {
width: Dimensions.get('screen').width,
height: Dimensions.get('screen').height,
},
inputView: {
backgroundColor: 'rgba(0,0,0,0)',
position: 'absolute',
top: 0,
left: 5,
right: 5,
},
input: {
height: 50,
padding: 10,
marginTop: 20,
marginLeft: 10,
marginRight: 10,
fontSize: 18,
borderWidth: 1,
borderRadius: 35,
borderColor: '#EEEEEE',
backgroundColor: 'white',
},
});
export default ShowMap;
Note: Kindly remove your API key in your code and please don't share it to public sites to protect your API key from unexpected usage.
Related
The (blue dot) marker doesn't response to user movements. I can get the current location of the user, but I can't figure how to update the location of the blue marker. I can use component and update its location, but I need to use blue dot marker because I need to have geolocator button on the top right hand side.
import React, { useState, useEffect } from "react";
import * as Location from "expo-location";
import { Dimensions, StyleSheet, Text, View } from "react-native";
import MapView, { Callout, Circle, Marker } from "react-native-maps";
export default function App() {
const [location, setLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
setErrorMsg("Permission to access location was denied");
return;
}
// let location = await Location.getCurrentPositionAsync({});
let watchID = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.High,
timeInterval: 500,
distanceInterval: 0
},
position => {
setLocation(position);
}
);
})();
}, []);
let text = "Waiting..";
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
}
return (
<View style={{ marginTop: 50, flex: 1 }}>
{location && (
<>
<Text style={styles.paragraph}>
{"lat:" + location.coords.latitude}
</Text>
<Text style={styles.paragraph}>
{"long:" + location.coords.longitude}
</Text>
<Text style={styles.paragraph}>
{"acurracy:" + location.coords.accuracy}
</Text>
</>
)}
<MapView
style={styles.map}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421
}}
provider="google"
showsUserLocation={true}
followsUserLocation={true}
// scrollEnabled={false}
>
{location && (
<Marker
coordinate={{
latitude: location.coords.latitude,
longitude: location.coords.longitude
}}
></Marker>
)}
</MapView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
},
map: {
width: Dimensions.get("window").width,
height: Dimensions.get("window").height
}
});
Thanks!
Adding followsUserLocation={true} props fixed my problem.
I have two-component classes. First is TrackRoute1.js from which I'm passing bus location parameters and also user current location parameters to class Dispaly.js through the server. But after displaying I keep getting a memory leak that indicates that it cant perform react state update on an unmounted component. I tried everything. But it won't help.!
TrackRoute1.js
import React, { Component } from "react";
import {
ActivityIndicator,
FlatList,
Text,
View,
TouchableHighlight,
StyleSheet,
} from "react-native";
import AnimatedRegion from "react-native-maps";
import Display1 from "./Display1";
import { LogBox } from "react-native";
import CustomHeader from "../CustomHeader";
LogBox.ignoreLogs(["Setting a timer"]);
import * as Location from 'expo-location';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true,
userLat: 0,
userLng: 0,
routeCoordinates: [],
distanceTravelled: 0,
prevLatLng: {},
coordinate: new AnimatedRegion({
userLat: 0,
userLng: 0,
latitudeDelta: 0,
longitudeDelta: 0
})
};
}
componentDidMount() {
this.interval = setInterval(() => this.getCoords(), 1000);
this._getLocationAsync();
}
async getCoords() {
fetch("https://api.thingspeak.com/channels/1323137/feeds.json?results=1")
.then((response) => response.json())
.then((json) => {
console.log(json.feeds, "API res");
this.setState({ data: json.feeds });
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({ isLoading: false });
});
}
_getLocationAsync = async () => {
console.log("123")
let { status } = await Location.requestForegroundPermissionsAsync();
console.log(status)
if (status !== 'granted') {
console.log('Permission to access location was denied');
return;
}
// Old method //
let location = await Location.getCurrentPositionAsync({});
console.log(location, "my location");
this.setState({
userLat: Number(location.coords.latitude),
userLng: Number(location.coords.longitude)
})
console.log(this.state.userLng,"userLng111")
// New Method //
// this.location = await Location.watchPositionAsync(
// {
// enableHighAccuracy: true,
// distanceInterval: 1,
// timeInterval: 1000
// },
// newLocation => {
// let { coords } = newLocation;
// // console.log(coords);
// this.setState({
// userLat: Number(coords.latitude),
// userLng: Number(coords.longitude)
// })
// },
// error => console.log(error)
// );
// return this.location;
};
calcDistance = newLatLng => {
const { prevLatLng } = this.state;
return haversine(prevLatLng, newLatLng) || 0;
};
componentWillUnmount() {
clearInterval(this.interval);
navigator.geolocation.clearWatch(this.watchID);
}
render() {
const { data, isLoading } = this.state;
return (
<View style={{ flex: 1, width: "100%" }}>
<CustomHeader title="Track Route" navigation={this.props.navigation} />
{isLoading ? (
<ActivityIndicator />
) : (
<FlatList
data={data}
keyExtractor={(id, index) => index.toString()}
renderItem={({ item }) => (
<Display1
value1={item.field1}
value2={item.field2}
value3={item.field3}
value4={this.state.userLat}
value5={this.state.userLng}
/>
)}
/>
)}
</View>
);
}
}
const styles = StyleSheet.create({
appButtonText: {
fontSize: 18,
color: "#fff",
fontWeight: "bold",
alignSelf: "center",
textTransform: "uppercase",
},
});
Dispaly.js
import React, { Component } from "react";
import {
StyleSheet,
View,
Text,
TouchableOpacity,
Platform,
Dimensions,
Image,
} from "react-native";
import * as Location from 'expo-location';
import MapView, {
PROVIDER_GOOGLE,
Marker,Polyline,
AnimatedRegion,
} from "react-native-maps";
import AutoScrolling from "react-native-auto-scrolling";
import { getPreciseDistance } from 'geolib';
const { width, height } = Dimensions.get("window");
export default class Map extends Component {
// constructor(props) {
// super(props);
// this.state = {
// };
// }
constructor(props) {
super(props);
this.marker = null;
this.timeout = null;
this.state = {
isMapReady: false,
userLat: 0,
userLng: 0,
Time:0,
Dis: 0,
hasLocationPermissions: false,
locationResult: null,
coordinate: new AnimatedRegion({
latitude: parseFloat(this.props.value1),
longitude: parseFloat(this.props.value2),
latitudeDelta: 0.05,
longitudeDelta: 0.04,
}),
};
}
async componentDidMount() {
this.mounted = true;
this.timeout = setTimeout(()=>{ var pdis = getPreciseDistance(
{latitude:parseFloat(this.props.value1), longitude: parseFloat(this.props.value2)},
{latitude: parseFloat(this.props.value4), longitude: parseFloat(this.props.value5)},
);
// console.log(
// `Precise Distance\n\n${pdis} Meter\nOR\n${pdis / 1000} KM`
// );
this.setState({Dis:pdis,Time:Math.round( pdis/(this.props.value3*1000) )})} ,2000)
this.setState({
Time:this.state.Time.toFixed(2)
})
}
componentWillUnmount = () =>{
this.mounted = false;
if (this.timeout) {
clearTimeout(this.timeout)
}
}
onMapLayout = () => {
this.setState({ isMapReady: true });
};
render() {
// console.log( this.state.userLat,
// this.state.userLng,"myConsole")
return (
<View>
{this.state.Dis !== 0 ?
<View style={{backgroundColor:"rgba(52, 52, 52, 0.00006)"}}>
<Text style={{ color: "green", fontWeight: "bold", marginTop: 10, alignSelf: "center", marginBottom: 3, }}>Bus is {this.state.Dis / 1000} km Away.</Text>
<AutoScrolling style={{ backgroundColor: "rgba(52, 52, 52, 0.00006)",
width: 400,
padding: 10,
marginBottom: 10,}} endPadding={50}>
<Text style={ {
color: "red",
fontSize: 20,
fontWeight: "bold",
textAlign: "center",
margin: 5,
}}>Bus is Coming in {this.state.Time} Minutes</Text>
</AutoScrolling>
</View>
:null }
<MapView
initialRegion={{
latitude: parseFloat(this.props.value1),
longitude: parseFloat(this.props.value2),
latitudeDelta: 0.02,
longitudeDelta: 0.01,
}}
onMapReady={this.onMapLayout}
provider={PROVIDER_GOOGLE}
loadingIndicatorColor="#e21d1d"
ref={(map) => (this.map = map)}
style={{
width,height
}}
loadingEnabled={true}
>
{this.state.isMapReady && (
<MapView.Marker
key="AIzaSyB8k3Irk81q1k8pbj5tPM33KRWNdtROoOg"
identifier="marker"
coordinate={{
latitude: parseFloat(this.props.value1),
longitude: parseFloat(this.props.value2),
}}
flat={false}
title="Route 1"
description = "Driver: Muhammad Murtaza"
>
<Image source={require("D:/React Native apps/Bus-Track1-main/assets/car-marker.png")} style={{ width: 60, height: 50 }}/>
</MapView.Marker>
)}
<MapView.Marker
key="AIzaSyArnXt8Xqydc3BF9Udt8JCkFuKqgPR_HM0"
identifier="marker1"
coordinate={{
latitude: parseFloat(this.props.value4),
longitude: parseFloat(this.props.value5)
}}
title="My Location"
/>
<Polyline
coordinates={[
{ latitude: parseFloat(this.props.value4),
longitude: parseFloat(this.props.value5)
},
{ latitude: parseFloat(this.props.value1),
longitude: parseFloat(this.props.value2)
},
]}
strokeColor="red"
strokeColors={[
'#238C23',
'red'
]}
strokeWidth={5}
/>
</MapView>
</View>
);
}
}
I have two-component classes. First is TrackRoute1.js from which I'm passing bus location parameters and also user current location parameters to class Dispaly.js through the server. But after displaying I keep getting a memory leak that indicates that it cant perform react state update on an unmounted component. I tried everything. But it won't help.!
I am new to using Getstate and UseState
Normally this works when i hard code the longitude and latitude its fine, now i want to get the longitude and latitude directly from an entered address.
i have set the values to setstate, but i am new to using setstate , use state.
I have written a Method that should get the address. So upon getting the address should resolve to getting the Longitude / latitude
This gets the Longitude and Latitude Well
GetLongitudeFromAddress = (txtaddress) =>{
let address = txtaddress;
let lng = this.state.Alongitude;
let lat = this.state.Alatitude;
var logLatApi = 'https://maps.googleapis.com/maps/api/geocode/json?address='+address+'&sensor=false&key=AIzaSyBsy6x3mTXbPQ52qk6XMI9u1NgMfn9-YNE';
var header = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
fetch(
logLatApi,{
method : 'GET',
headers : header
}
).then((response) => response.json())
.then((responseJson)=>{
if(responseJson.status ==='OK')
{
this.setState({longitude: responseJson.results[0].geometry.location.lng});
this.setState({latitude: responseJson.results[0].geometry.location.lat});
}
})
}
Now I want to use this in my setstate / usestate here
const [coordinates] = useState([
{
latitude: 6.450430,
longitude: 3.390460,
},
{
latitude: 6.430980,
longitude: 3.435880,
},
]);
How can I do this? My code in full looks like this :
import React , {useState} from 'react';
import {StyleSheet, View, Dimensions, TextInput} from 'react-native';
import MapView , { Marker , Polyline } from 'react-native-maps';
import MapViewDirections from 'react-native-maps-directions';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
this.state = {
Address : '',
Alongitude : '',
Alatitude: '',
};
GetLongitudeFromAddress = (txtaddress) =>{
let address = txtaddress;
let lng = this.state.Alongitude;
let lat = this.state.Alatitude;
var logLatApi = 'https://maps.googleapis.com/maps/api/geocode/json?address='+address+'&sensor=false&key=AIzaSyBsy6x3mTXbPQ52qk6XMI9u1NgMfn9-YNE';
var header = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
fetch(
logLatApi,{
method : 'GET',
headers : header
}
).then((response) => response.json())
.then((responseJson)=>{
if(responseJson.status ==='OK')
{
this.setState({longitude: responseJson.results[0].geometry.location.lng});
this.setState({latitude: responseJson.results[0].geometry.location.lat});
}
})
}
const ShowMap =() =>{
const [coordinates] = useState([
{
latitude: 6.450430,
longitude: 3.390460,
},
{
latitude: 6.430980,
longitude: 3.435880,
},
]);
return(
<View style={styles.container}>
<MapView
style={styles.maps}
initialRegion={{
latitude: coordinates[0].latitude,
longitude: coordinates[0].longitude,
latitudeDelta: 0.0622,
longitudeDelta: 0.0121,
}}>
<MapViewDirections
origin={coordinates[0]}
destination={coordinates[1]}
apikey="AIzaSyBsy6x3mTXbPQ52qk6XMI9u1NgMfn9-YNE"
strokeWidth={4}
strokeColor="#FD0631"
/>
<Marker coordinate={coordinates[0]} />
<Marker coordinate={coordinates[1]} />
</MapView>
<View style={styles.inputView}>
<TextInput
style={styles.input}
placeholder="Origin"
onChange={this.GetLongitudeFromAddress()}
/>
<TextInput
style={styles.input}
placeholder="Destination"
onChange={this.GetLongitudeFromAddress()}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
maps: {
width: Dimensions.get('screen').width,
height: Dimensions.get('screen').height,
},
inputView:{
backgroundColor: 'rgba(0,0,0,0)',
position: 'absolute',
top: 0,
left: 5,
right: 5
},
input: {
height: 50,
padding: 10,
marginTop: 20,
marginLeft: 10,
marginRight: 10,
fontSize: 18,
borderWidth: 1,
borderRadius: 35,
borderColor: '#EEEEEE',
backgroundColor: 'white',
}
});
export default ShowMap;
Please assist I am a bit confused here. I just need it to dynamically get it and show directions in the map.
To start off, you need a new hook, to get your API to run. Achieve this by using useEffect.
UseEffect with an empty array dependency will only run your API once on load. With the results from the API, use the set method from useState to update the Coordinates variable. You may then see the Coordinates updated dynamically.
const ShowMap =() =>{
const [Coordinates, setCoordinates] = useState();
useEffect(() => {
(async () => {
const result = GetLongitudeFromAddress(param);
setCoordinates(result);
})();
}, []);
return (<Map/>)
}
when i use image inside i get error index=5 count=2 can anyone help i want to create ployline between markers and when user clicks on marker they should get ployine and image but i am getting polyline but when i use i get error index=5 count=2 and app crashes[enter image description here][1]
//explorescreen.js code
import React from 'react';
import MapView from 'react-native-maps';
import Geolocation from '#react-native-community/geolocation';
import { View, Text, Dimensions, Animated, StyleSheet, Image } from 'react-native';
import Polyline from '#mapbox/polyline';
const { width, height } = Dimensions.get('screen')
const locations = require('../locations')
export default class ExploreScreen extends React.Component {
state = {
latitude: null,
longitude: null,
locations: locations,
direct: false
}
componentDidMount() {
this.GetLocations();
}
GetLocations = async () => {
Geolocation.getCurrentPosition(
({ coords: { latitude, longitude } }) => this.setState({ latitude, longitude }, this.mergeCoords),
(error) => console.log('Error:', error)
)
const { locations: [sampleLocation] } = this.state
this.setState({
desLatitude: sampleLocation.coords.latitude,
desLongitude: sampleLocation.coords.longitude,
}, this.mergeCoords)
}
mergeCoords = () => {
const { latitude, longitude, desLatitude, desLongitude } = this.state
const hasStartAndEnd = (latitude !== null && desLatitude !== null)
// if the line have start and end
if (hasStartAndEnd) {
const concatStart = `${latitude},${longitude}`
const concatEnd = `${desLatitude},${desLongitude}`
this.getDirections(concatStart, concatEnd)
}
}
async getDirections(startLoc, desLoc) {
try {
const resp = await fetch(`https://maps.googleapis.com/maps/api/directions/json?origin=${startLoc}&destination=${desLoc}&key=AIzaSyDoWUeYVrFse7r76yOMX9dAMgelIlNVGSY`)
const resJson = await resp.json();
const points = Polyline.decode(resJson.routes[0].overview_polyline.points);
const coords = points.map(point => {
return {
latitude: point[0],
longitude: point[1]
}
})
this.setState({ coords, direct: true })
} catch (err) {
console.log('Error: ', err)
}
}
onMarkerPress = location => () => {
const { coords: { latitude, longitude } } = location
this.setState({
destination: location,
desLatitude: latitude,
desLongitude: longitude
}, this.mergeCoords)
}
renderMarkers = () => {
const { locations } = this.state
return (
<View>
{
locations.map((location, index) => {
const {
coords: { latitude, longitude }
} = location
return (
<MapView.Marker
key={index}
coordinate={{ latitude, longitude }}
onPress={this.onMarkerPress(location)}>
<Animated.View style={[styles.markerWrap]}>
<Animated.Image
source={require('../assests/images/marker.png')}
style={styles.marker}
resizeMode="cover" />
</Animated.View>
</MapView.Marker>
)
})
}
</View>
)
}
render() {
const { latitude, longitude, coords, destination } = this.state
if (latitude) {
return (
<MapView
showsUserLocation
style={{ flex: 1 }}
initialRegion={{
latitude,
longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
userLocationPriority: 'high',
userLocationFastestInterval: 8000,
}}
>
{this.renderMarkers()}
{this.state.direct &&
<MapView.Polyline
strokeWidth={2}
strokeColor="purple"
coordinates={coords}
/>
}
<Image
source={{ uri: destination && destination.image_url }}
style={{
flex: 1,
width: width * 0.95,
alignSelf: 'center',
height: height * 0.15,
position: 'absolute',
bottom: height * 0.05
}}
/>
</MapView>
);
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>We need your permissions !!</Text>
</View>
)
}[enter image description here][1]
}
const styles = StyleSheet.create({
markerWrap: {
alignItems: "center",
justifyContent: "center",
width: 50,
height: 50,
}, marker: {
width: 30,
height: 30,
},
})
[1]: https://i.stack.imgur.com/JiO3g.png
Problem:
I have created a react native application with expo clii. In there I am using react-native-maps.With expo app It was very worked. But after building the standalone app and when I try to open it it did not navigate to that component.It mean when I click on the location tab it restart the app.This is my that component code.
import React, { Component } from "react";
import {
StyleSheet,
KeyboardAvoidingView,
View,
ActivityIndicator,
TouchableOpacity,
TextInput,
Text,
Image,
ScrollView,
Dimensions
} from "react-native";
import MapView from "react-native-maps";
import PageHeader from "../Shared/pageHeader/PageHeader";
const windowheight = (Dimensions.get("window").height * 75) / 100;
const windowwidth = (Dimensions.get("window").width * 80) / 100;
class Location extends Component {
constructor(props) {
super(props);
this.state = {
focusedLocation: {
latitude: 6.9336686,
longitude: 79.8489527,
latitudeDelta: 0.0322,
longitudeDelta:
(Dimensions.get("window").width / Dimensions.get("window").height) *
0.0322
},
locationChosen: false,
placesList: [],
isFocused: false
};
}
static navigationOptions = {
header: null
};
componentDidMount() {
navigator.geolocation.getCurrentPosition(
pos => {
const coordsEvent = {
nativeEvent: {
coordinate: {
latitude: pos.coords.latitude,
longitude: pos.coords.longitude
}
}
};
this.pickLocationHandler(coordsEvent);
},
err => {
console.log(err);
alert("Fetching the Position failed");
}
);
}
reloadLocation = () => {
navigator.geolocation.getCurrentPosition(
pos => {
const coordsEvent = {
nativeEvent: {
coordinate: {
latitude: pos.coords.latitude,
longitude: pos.coords.longitude
}
}
};
this.pickLocationHandler(coordsEvent);
},
err => {
console.log(err);
alert("Fetching the Position failed");
}
);
};
pickLocationHandler = event => {
this.setState({ locationChosen: true });
const coords = event.nativeEvent.coordinate;
let placesList = [];
let places = [];
this.map.animateToRegion({
...this.state.focusedLocation,
latitude: coords.latitude,
longitude: coords.longitude
});
const apikey = "AIzaSyDsA9zWFxw__OiApEKhbUEqVL4VQ_uN0hc";
fetch(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=" +
coords.latitude +
"," +
coords.longitude +
"&radius=800" +
"&type=parking" +
"&key=" +
apikey
)
.then(response => response.json())
.then(responseJson => {
if (responseJson) {
placesList = responseJson.results;
placesList.map((el, index) => {
var place = {
title: el.name,
coordinates: {
latitude: el.geometry.location.lat,
longitude: el.geometry.location.lng
}
};
places.push(place);
});
this.setState({ placesList: places });
}
});
};
componentWillUnmount = () => {
this.setState(prevState => {
return {
focusedLocation: {
...prevState.focusedLocation,
latitude: 6.9336686,
longitude: 79.8489527
},
locationChosen: false,
placesList: []
};
});
};
render() {
let marker = null;
if (this.state.locationChosen) {
marker = <MapView.Marker coordinate={this.state.focusedLocation} />;
}
const places = this.state.placesList;
return (
<View>
<PageHeader
title="Nearby Parking"
image={require("../../../assets/shape.png")}
width="4%"
marginTop="1.5%"
marginLeft="40%"
></PageHeader>
<View
style={{
marginTop: "2%",
marginBottom: "2%",
marginLeft: "2%",
marginRight: "2%"
}}
>
<MapView
style={styles.map}
provider="google"
initialRegion={this.state.focusedLocation}
showsUserLocation={true}
zoomControlEnabled={true}
style={styles.map}
onPress={this.pickLocationHandler}
onUserLocationChange={this.reloadLocation}
ref={ref => (this.map = ref)}
>
{places.map((place, index) => {
return (
<MapView.Marker
key={index}
coordinate={place.coordinates}
title={place.title}
pinColor="red"
tooltip={true}
/>
);
})}
{marker}
</MapView>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
map: {
height: "100%",
width: "100%"
},
button: {
margin: 8,
backgroundColor: "#fff",
borderWidth: 1,
borderColor: "#fff",
alignItems: "center",
justifyContent: "center",
width: 50,
height: 50,
borderRadius: 100,
marginTop: windowheight,
marginLeft: windowwidth
},
callout: {},
calloutButton: {
marginTop: windowheight,
marginLeft: windowwidth,
borderWidth: 1,
borderColor: "rgba(0,0,0,0.2)",
alignItems: "center",
justifyContent: "center",
width: 50,
height: 50,
backgroundColor: "#2b78fe",
borderRadius: 100,
shadowColor: "#e9ebee"
}
});
export default Location;
Can someone tell me what kind of reason would cause this issue.Thank you.
Modify the following
Add flex: 1 to your parent view:
// ... other code
<View style={{ flex: 1 }}> <=== add flex here
<PageHeader
title="Nearby Parking"
image={require("../../../assets/shape.png")}
// ... other code
Change your map styling to the following:
map: {
flex: 1
}
Remove the duplicate declaration of style on the
// ... other code
<MapView
style={styles.map}
provider="google"
initialRegion={this.state.focusedLocation}
showsUserLocation={true}
zoomControlEnabled={true}
style={styles.map} <=== remove this
onPress={this.pickLocationHandler}
onUserLocationChange={this.reloadLocation}
ref={ref => (this.map = ref)}>
// ... other code
The correct way to use the GOOGLE provider
import MapView, { PROVIDER_GOOGLE, Marker } from 'react-native-maps'
// ... other code
<MapView
style={styles.map}
provider={PROVIDER_GOOGLE} <=== make this chage
initialRegion={this.state.focusedLocation}
showsUserLocation={true}
zoomControlEnabled={true}
style={styles.map}
onPress={this.pickLocationHandler}
onUserLocationChange={this.reloadLocation}
ref={ref => (this.map = ref)}>
// ... other code
Hope this Helps!