React native maps jumps back to region on release - react-native

I use react-native maps - Mapview in my React Native app. On Android, the code works as expected, the location of the user is used to determine the region. This will be included in this.state.latitude and this.state.longtitude. Only on iOS I have the problem that when I 'scroll' on the map it jumps back to the region after releasing it. If I put the code on initialRegion I end up somewhere in a sea and the user has to scroll indefinitely. Does anybody have experience with this?
after setting code to initialRoute:
The current code:
import React, {Component} from 'react';
import {StyleSheet, Text, View,ScrollView, SafeAreaView, ImageBackground, Button,TouchableOpacity, Alert, Image, Linking, ActivityIndicator} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { ListItem, ThemeConsumer } from 'react-native-elements'
import { Marker, PROVIDER_GOOGLE } from "react-native-maps";
//import { ClusterMap } from "react-native-cluster-map";
import MapView from "react-native-map-clustering";
import firebase from 'react-native-firebase';
import Geolocation from '#react-native-community/geolocation';
import LaunchNavigator from 'react-native-launch-navigator';
if(Platform.OS === "android") LaunchNavigator.setGoogleApiKey("API KEY");
class locationScreen extends Component {
constructor(props){
super(props);
this.state = {
cities : [ ],
totalStores: 0,
latitude:0,
longitude: 0,
nearestPlace: null,
}
}
deg2Rad = (deg) => {
return deg * Math.PI / 180;
}
pythagorasEquirectangular = (lat1, lon1, lat2, lon2) => {
lat1 = this.deg2Rad(lat1);
lat2 = this.deg2Rad(lat2);
lon1 = this.deg2Rad(lon1);
lon2 = this.deg2Rad(lon2);
const R = 6371;
const x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
const y = (lat2 - lat1);
const d = Math.sqrt(x * x + y * y) * R;
return d;
}
nearestCity = (latitude, longitude) => {
let mindif = 99999;
let closest;
for (let index = 0; index < this.state.cities.length; index++) {
const dif = this.pythagorasEquirectangular(latitude, longitude, this.state.cities[index].lat,
this.state.cities[index].long);
if (dif < mindif) {
closest = index;
mindif = dif;
}
}
this.setState({
nearestPlace: closest,
})
this.state.cities.forEach(i =>{
if( i.name == this.state.cities[this.state.nearestPlace].name) i.nearest = 1 ;
})
this.setState({
cities: this.state.cities,
})
// this.nearestPlace = closest
// return cities= closest;
}
navigateTo = (item) => {
console.log(item.street);
LaunchNavigator.navigate(item.street + "," + item.zip+ ","+ item.city)
.then(() => console.log("Launched navigator"))
.catch((err) => console.error("Error launching navigator: "+err));
}
setCurrentDirections = () =>{
Geolocation.getCurrentPosition(position => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
desLat: position.coords.latitude,
desLong: position.coords.longitude,
error: null,
});
console.log("reached function");
console.log("latitude: " + this.state.latitude);
console.log("Longtitude: " + this.state.longitude);
})
}
setNearestonClick= (clickId) =>{
this.state.cities.forEach(i =>{
if( i.name == clickId) i.nearest = 1 ;
})
this.setState({
cities: this.state.cities,
})
}
onItemClickHandler= (url)=>{
Linking.openURL(url)
}
/* PressedLocation = (data) =>{
console.log('location:' + data.lat + 'long ' +data.long );
this.setState({
latitude: data.lat,
longitude: data.long,
error: null,
});
}
*/
markerCliked = (id) =>{
console.log("id is: " + id);
}
latitude= 0;
longitude= 0;
componentDidMount(){
this.setCurrentDirections();
let ref = firebase.database().ref('stores');
ref.on('value' , snapshot =>{
var state = snapshot.val();
this.setState({
cities: state,
totalStores: state.length,
})
this.nearestCity(this.state.latitude, this.state.longitude);
})
}
render(){
const { cities } = this.state;
return(
<ScrollView style={styles.scorllVert}>
<SafeAreaView style={styles.container}>
<View style={styles.headerLeft}>
<TouchableOpacity style={styles.menubar} onPress={this.props.navigation.openDrawer}>
<Icon name="bars" size={24}/>
</TouchableOpacity>
</View>
<View style={styles.headerCenter}>
<Image source={require('./assets/images/all/logo-snackpoint.png')} style={styles.logoSnackpoint} />
</View>
<View style={styles.headerRight}>
<TouchableOpacity style={styles.userIcon}>
<Icon name="user-circle" size={24} onPress={this.props.navigation.openDrawer}/>
</TouchableOpacity>
</View>
</SafeAreaView>
<View style={styles.headerStores}>
<Text style={styles.headerStoresText}>Aantal vestigingen: {this.state.totalStores}</Text>
</View>
<View style={styles.containerContent}>
<View style={styles.page}>
<View style={styles.containerMap}>
<MapView
showsUserLocation={true}
style={{ flex: 1 }}
onClusterPress={() => this.markerCliked()}
region={{
latitude: this.state.latitude,
longitude: this.state.longitude,
latitudeDelta: 0.015,
longitudeDelta: 0.0121
}}
>
{
this.state.cities.map(marker => (
<Marker key={marker.name} coordinate={{latitude: marker.lat, longitude: marker.long}} onPress={() => this.setNearestonClick(marker.name)}/>
))
}
</MapView>
</View>
</View>
<View style={styles.stores}>
{
this.state.cities.sort(function(a, b) {
if(a.nearest) return -1;
if(b.nearest) return 1;
if(a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if(a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
}).map((marker, i) => (
<TouchableOpacity onPress={() => this.navigateTo(marker)} >
<View style={styles.store}>
<View style={styles.leftcolumn}>
<Text style={styles.storeTitle}>{marker.name}</Text>
<Text>{marker.street}</Text>
<Text>{marker.zip}, {marker.city}</Text>
<Text>Telefoon: {marker.phone}</Text>
</View>
<View style={styles.midcolumn}>
<Text>Ma:</Text>
<Text>Di:</Text>
<Text>Wo:</Text>
<Text>Do:</Text>
<Text>Vr:</Text>
<Text>Za:</Text>
<Text>Zo:</Text>
</View>
<View style={styles.rightcolumn}>
<Text>{marker.monday}</Text>
<Text>{marker.tuesday}</Text>
<Text>{marker.wednesday}</Text>
<Text>{marker.thursday}</Text>
<Text>{marker.friday}</Text>
<Text>{marker.saturday}</Text>
<Text>{marker.sunday}</Text>
</View>
</View>
<View style={{borderBottomColor: '#C8C8C8',borderBottomWidth: 1,}}/>
</TouchableOpacity>
))
}
</View>
</View>
</ScrollView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
marginBottom: 13
},
text:{
color: "#161924",
fontSize: 20,
fontWeight: "500",
},userIcon:{
paddingTop: 22,
paddingRight: 0,
alignItems: 'flex-end',
},
logoSnackpoint:{
width: 180,
height: 52,
marginTop: 12,
},
headerLeft:{
width: '33%',
},
headerCenter:{
width: '30%',
alignItems: 'center',
},
headerRight:{
width: '30%',
},
menubar:{
paddingTop: 22,
paddingLeft: 20
},
containerContent:{
padding: 0,
paddingBottom: 30
},
title:{
fontSize: 35
},
textTitle:{
marginTop: 10,
},
titleRed:{
fontSize: 25,
color: '#CC2929',
marginTop: 30,
marginBottom: 10
},
map: {
flex: 1
},
page: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
},
containerMap: {
height: 300,
width: '100%',
backgroundColor: "tomato"
},
headerStores:{
width: '100%',
backgroundColor: '#CD2929',
textAlign: 'center',
paddingTop: 20,
paddingBottom: 20
},
headerStoresText:{
color: 'white',
textAlign: 'center'
},
store:{
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
width: '100%',
padding: 20
},
leftcolumn:{
width: "50%",
},
midcolumn:{
width: "20%",
},
rightcolumn:{
width: "30%",
},
storeTitle:{
color: '#CD2929',
fontWeight: "bold",
fontSize: 30
},
hr:{
backgroundColor: 'grey',
padding: 5
}
});
export default locationScreen;

It looks like that there is a problem when setting the region property within the MapView.
From my code, I removed the part that looks like this from the MapView
region=
{{
latitude: this.state.latitude,
longitude: this.state.longitude,
latitudeDelta: 0.015,
longitudeDelta: 0.0121
}}
and I can scroll back again.
But then, you'll have to find a way to set the region, it looks buggy with this component. Especially with class components.

initialRegion is uncontrolled state, the map will only set to the region on initial load, so if you set it before your region is defined it will focus on lat:0, lng: 0 -- out in the ocean. So before you render your map, make sure the region is defined.
region is controlled state, as the map redraws it will use the most recent region definition. If you drag the map, and the region doesn't update doesn't get updated to the new location, the next redraw of the map will go to whatever the region was last defined as. handleRegionChangeComplete can be used to update the region as you move, but you can run into jumpiness if multiple redraws are occurring at the same time.

Related

React-native Sending information between pages?

Hello, I want to redirect Mapview.js to ShowInfo.js page. I want to
send ** locInfo ** information while redirecting. locInfo is a
variable defined in ShowInfo. How can I do this in Mapview.js.
I get an error when I write this code in Mapview.js.
Actions.ShowInfo({locationID: this.props.locID })
My purpose; Location information, pictures descriptions etc. from Mapview.js to ShowInfo. Send.
Mapview.js
import React from 'react';
//import {View, Text} from 'react-native';
import { getDistance, getPreciseDistance } from 'geolib';
import MapView, { Marker, PROVIDER_GOOGLE, Callout } from 'react-native-maps';
import Geolocation from '#react-native-community/geolocation';
import {
StyleSheet,
Image,
View,
Dimensions,
TouchableOpacity,
Text,
} from 'react-native';
const { width, height } = Dimensions.get('window');
import LinearGradient from 'react-native-linear-gradient';
import MapViewDirections from 'react-native-maps-directions';
import ImagePicker from 'react-native-image-picker';
export default class Mapview extends React.Component {
constructor(props) {
super(props);
this.state = {
latitude: 0,
longitude: 0,
error: null,
coords: [],
places: null,
selectedLat: "",
selectedLang: "",
distance: "",
};
}
getLocation = () => {
Geolocation.getCurrentPosition(position => {
this.setState({ latitude: position.coords.latitude })
this.setState({ longitude: position.coords.longitude })
}
);
}
setLatLang = (lat, lng) => {
this.setState({ selectedLat: lat })
this.setState({ selectedLang: lng })
}
showCoords() {
const arrayMarkers = [];
var coordsLatLang = [];
var allCoords = [];
var selectedCoordLat = [];
var selectedCoordLang = [];
var dis = [];
Geolocation.getCurrentPosition(position => {
var userLat = position.coords.latitude
var userLang = position.coords.longitude
for (let index = 0; index < this.props.locCoord.length; index++) {
coordsLatLang = this.props.locCoord[index].split(',')
allCoords.push(this.props.locCoord[index].split(','))
selectedCoordLat.push(allCoords[index][0])
selectedCoordLang.push(allCoords[index][1])
dis.push(getDistance(
{ latitude: userLat, longitude: userLang },
{ latitude: selectedCoordLat[index], longitude: selectedCoordLang[index] }
))
var lat = coordsLatLang[0]
var lng = coordsLatLang[1]
arrayMarkers.push(
< Marker
pinColor={'#24012f'}
coordinate={{
latitude: Number(lat),
longitude: Number(lng),
}}
>
<Callout tooltip style={{ position: 'relative' }} onPress={() => this.setLatLang(selectedCoordLat[index], selectedCoordLang[index])}>
<LinearGradient start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={{ borderRadius: 20 }} colors={['#531c5c', '#4b5cab']}>
<View style={{ flexDirection: 'column', alignContent: 'center', alignItems: 'center', flex: 1, padding: 15 }}>
<Text style={{ color: "white", fontWeight: 'bold', fontSize: 20 }}>{this.props.locNames[index]}</Text>
<Text style={{ marginTop: 5, color: "white" }}>Puanı:{this.props.TourLocRating[index].toFixed(2)}</Text>
<Text style={{ color: "white" }}>Mesafe:{(dis[index] / 1000).toFixed(2)}KM</Text>
<Text style={{ marginTop: 5, color: "white", marginBottom: 5 }}>Rota Oluşturmak İçin Tıklayın!</Text>
</View>
</LinearGradient>
</Callout>
</Marker >
)
}
}
)
this.setState({ places: arrayMarkers })
}
openCam() {
ImagePicker.launchCamera((response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
this.setState({
avatarSource: source,
});
}
});
}
componentWillMount() {
this.showCoords();
}
componentDidMount() {
this.getLocation();
}
render() {
console.log(this.props.images)
return (
<View style={{ flex: 1 }}>
<View style={{
backgroundColor: 'white',
alignItems: 'center',
width: width,
height: height * 0.08,
fontWeight: "bold",
flexDirection: 'row',
justifyContent: 'flex-start',
}}>
<TouchableOpacity onPress={() => { this.props.navigation.goBack() }}>
<Image
style={{ width: width * 0.05, height: height * 0.03, marginTop: 15, marginBottom: 10, marginLeft: 5 }}
source={require('../../img/back.png')}
/>
</TouchableOpacity>
<Image resizeMode="contain" style={{ marginLeft: width * 0.17 }}
source={require('../../img/headerText.png')}
/>
</View>
<View style={[styles.lineFooterStyle]} />
<MapView
provider={PROVIDER_GOOGLE}
region={{
latitude: this.state.latitude,
longitude: this.state.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
showsUserLocation={true}
style={{ flex: 1 }}
>
{this.state.places}
<MapViewDirections
precision={"high"}
origin={{ latitude: this.state.latitude, longitude: this.state.longitude }}
destination={{ latitude: this.state.selectedLat, longitude: this.state.selectedLang }}
apikey={'s-v8lEdDbtagGsssssasaNp5ogtAA8ok'}
strokeWidth={6}
strokeColor="#531959"
/>
</MapView>
<View>
<TouchableOpacity style={{ width: width * 0.2, height: width * 0.2, marginTop: -height * 0.17, marginLeft: width * 0.4 }} onPress={() => this.openCam()}>
<Image style={{ width: width * 0.2, height: width * 0.2, marginTop: 15, borderRadius: 25 }}
source={require('../../img/ARLogo.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}
ShowInfo.js
import React from 'react';
import { Actions } from 'react-native-router-flux';
import {
StyleSheet,
Text,
ScrollView,
Image,
View,
Dimensions,
TouchableOpacity,
TextInput
} from 'react-native';
import { AirbnbRating, Rating } from 'react-native-ratings';
import LinearGradient from 'react-native-linear-gradient';
import * as firebase from 'firebase';
import { SliderBox } from "react-native-image-slider-box";
const { width, height } = Dimensions.get('window');
import Comment from '../HorizontalSlider/Comment';
let userRef = db.ref('/Users');
let commentsRef = db.ref('/LocationComments');
let locationRef = db.ref('/Location');
import { db } from '../../components/dbConfig/config';
if (!firebase.apps.length) {
firebase.initializeApp(db);
}
const rootRef = firebase.database().ref();
const loccommentRef = rootRef.child('LocationComments');
let addItem = (comment, locationID, userName, rating, comments, locID) => {
loccommentRef.push({
comment: comment,
LocationID: locationID,
username: userName,
users: [],
rating: rating
});
var count = 0;
var newRating = 0;
for (let index = 0; index < comments.length; index++) {
if (locID == comments[index].LocationID) {
count++;
newRating += comments[index].rating
}
}
var generalNewRating = (newRating + rating - 1) / count
locationRef.child(locID).update({ 'Rating': generalNewRating })
};
export default class ShowInfo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
locInfo: [],
comments: [],
comment: '',
userName: '',
userEmail: '',
rating: '',
users: [],
};
}
ratingCompleted = (rating) => {
this.setState({ rating: rating })
}
getUserData() {
userRef.on('value', snapshot => {
let data = snapshot.val();
let users = Object.values(data);
this.setState({ users: users });
});
}
getComments() {
commentsRef.on('value', snapshot => {
let data = snapshot.val();
let comments = Object.values(data);
this.setState({ comments: comments });
});
}
getLocationData() {
locationRef.on('value', snapshot => {
let data = snapshot.val();
let locInfo = Object.values(data);
this.setState({ locInfo: locInfo });
});
}
getUserName = () => {
for (let index = 0; index < this.state.users.length; index++) {
if (this.props.userEmail == this.state.users[index].email) {
return this.state.users[index].username;
}
}
}
updateRating = () => {
var count = 0;
for (let index = 0; index < this.state.comments.length; index++) {
if (this.props.locID == this.state.comments[index].LocationID) {
count++;
}
}
locationRef.child(this.props.locID).update({ 'Rating': (this.state.locInfo[this.props.locID].Rating + this.state.rating) / count })
}
componentWillMount() {
this.getLocationData()
this.getUserData()
this.getComments()
}
inRender(images, commentContext, comments, locCoord, locNames) {
console.log(this.state.locInfo[2].Rating, "---")
if (this.getUserName() != null) {
this.setState({ userName: this.getUserName() })
}
for (let index = 0; index < this.state.locInfo.length; index++) {
if (this.props.locID == this.state.locInfo[index].ID) {
images = this.state.locInfo[index].Image.split(',')
locCoord.push(this.state.locInfo[index].Coordinate)
console.log(locCoord)
locNames.push(this.state.locInfo[index].Name)
}
}
for (let index = 0; index < this.state.comments.length; index++) {
if (this.props.locID == this.state.comments[index].LocationID) {
comments.push(this.state.comments[index])
}
}
for (let index = 0; index < comments.length; index++) {
if (comments[index].username != "") {
commentContext.push(
<Comment
username={comments[index].username}
comment={comments[index].comment}
rating={comments[index].rating}
/>
)
}
}
return images;
}
render() {
var locNames = [];
var images = [];
var comments = [];
var commentContext = [];
var locCoord = []
var retImages = this.inRender(images, commentContext, comments, locCoord, locNames);
var TourLocRating = [];
TourLocRating.push(this.props.rating)
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<View style={{
backgroundColor: 'white',
alignItems: 'center',
width: width,
height: height * 0.08,
fontWeight: "bold",
flexDirection: 'row',
justifyContent: 'flex-start',
}}>
<TouchableOpacity onPress={() => { this.props.navigation.goBack() }}>
<Image
style={{ width: width * 0.05, height: height * 0.03, marginTop: 15, marginBottom: 10, marginLeft: 5 }}
source={require('../../img/back.png')}
/>
</TouchableOpacity>
<Image resizeMode="contain" style={{ marginLeft: width * 0.17 }}
source={require('../../img/headerText.png')}
/>
</View>
<View style={[styles.lineFooterStyle]} />
<ScrollView>
<SliderBox
style={{ height: height * 0.4, marginLeft: 5, marginRight: 5 }}
imageLoadingColor="white"
dotColor="white"
inactiveDotColor="#90A4AE"
autoplay
disableOnPress
circleLoop
images={retImages}
//currentImageEmitter={index => locName=imgSliderHolder[index].Name} //Resim üzerinde lokasyonun adını gösterebilirsin. Resim geldiğinde gerçekleşen func.
//onCurrentImagePressed={index => Actions.ShowInfo({ locImage: images[index], tourName: imgSliderHolder[index].Name, info: imgSliderHolder[index].Info })}
/>
<View style={{ marginLeft: 15 }}>
<View style={{ flexDirection: 'row' }}>
<View style={{ flexDirection: 'column' }}>
<View style={{ marginTop: 30 }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginLeft: height * 0.01 }}>{this.props.tourName}</Text>
<LinearGradient style={styles.gradientLineStyle} start={{ x: 0, y: 1 }} end={{ x: 1, y: 1 }} colors={['#3E276F', '#F9F7F6']}></LinearGradient>
</View>
<TouchableOpacity style={styles.BtnStyleLogin} onPress={() => Actions.LocMapview({ locCoord: locCoord, locNames, kind: "location", TourLocRating })}>
<Text style={{ color: 'white' }}>
Başla
</Text>
</TouchableOpacity>
<View style={{ flexDirection: 'row' }}>
<Rating
readonly={true}
startingValue={this.props.rating}
style={{ paddingVertical: 10 }}
imageSize={20}
/>
<Text style={{ marginLeft: width * 0.02, marginBottom: height * 0.015, marginTop: height * 0.012, fontWeight: 'bold' }}>Puanı:{this.props.rating.toFixed(2)}</Text>
</View>
</View>
<TouchableOpacity onPress={() => this.playSound()}>
<Image style={{ width: 40, height: 40, marginTop: height * 0.1, }}
source={require('../../img/sound_button.png')}
/>
</TouchableOpacity>
</View>
<View style={{ flexDirection: 'row', marginBottom: 15, marginTop: 15, justifyContent: 'space-between' }}>
<TouchableOpacity onPress={() => { this.refs._scrollView.scrollTo(); }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginLeft: height * 0.025 }}>Hakkında</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => { this.refs._scrollView.scrollTo({ x: width, y: 0 }); }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginRight: 15 }}>Değerlendir</Text>
</TouchableOpacity>
</View>
<LinearGradient style={styles.gradientLineStyle} start={{ x: 0, y: 1 }} end={{ x: 1, y: 1 }} colors={['#3E276F', '#F9F7F6']}></LinearGradient>
</View>
<ScrollView
ref='_scrollView'
horizontal={true}
pagingEnabled={true}
>
<View style={{
flex: 1,
width: width,
}}>
<Text style={{ padding: 15, textAlign: 'justify' }}>{this.props.info}</Text>
</View>
<View
style={{
flex: 1,
width: width,
padding: 15
}}>
<TextInput
style={{ height: 150, borderColor: 'gray', borderWidth: 0.5, borderRadius: 25 }}
multiline={true}
onChangeText={comment => this.setState({ comment })}
/>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<View style={{ marginTop: 20 }}>
<AirbnbRating
count={5}
showRating={false}
onFinishRating={this.ratingCompleted}
defaultRating={0}
size={30}
fractions={2}
/>
</View>
<TouchableOpacity style={{
width: width * 0.3,
height: height * 0.06,
marginTop: 15,
marginBottom: 15,
borderRadius: 15,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#1a345c',
flexDirection: 'row',
}} onPress={() => addItem(this.state.comment, this.props.locID, this.state.userName, this.state.rating, this.state.comments, this.props.locID)}>
<Text style={{ color: 'white' }}>
Değerlendir
</Text>
</TouchableOpacity>
</View>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 25, marginTop: 15 }}>Yorumlar</Text>
{commentContext}
</View>
</ScrollView>
</ScrollView>
<View style={styles.lineFooterStyle} />
<View style={styles.footerStyle}>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Mainpage")}>
<Image style={styles.navItemHomeStyle}
source={require('../../img/Home.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Discover")}>
<Image style={styles.navItemBookmarkStyle}
source={require('../../img/Bookmark_2.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("MyProfile")}>
<Image style={styles.navItemProfileStyle}
source={require('../../img/Profile.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}

Simple error I get while redirecting from LocMapview.js to => ShowInfo.js

When I click the map in React-native, I am trying to redirect. But I'm getting an error. mapview.js => I'm redirecting ShowInfo.js.
The code I'm redirecting to:
ShowInfo.js
Actions.ShowInfo({ rating: this.props.rating, locID: this.props.locID, images: this.state.imgLink, tourName: this.props.name, info: this.props.info }) // The Code I'm Redirecting
Mapview.js Code Text
import React from 'react';
//import {View, Text} from 'react-native';
import { getDistance, getPreciseDistance } from 'geolib';
import MapView, { Marker, PROVIDER_GOOGLE, Callout } from 'react-native-maps';
import Geolocation from '#react-native-community/geolocation';
import { Actions } from 'react-native-router-flux';
import {
StyleSheet,
Image,
View,
Dimensions,
TouchableOpacity,
Text,
} from 'react-native';
const { width, height } = Dimensions.get('window');
import LinearGradient from 'react-native-linear-gradient';
import MapViewDirections from 'react-native-maps-directions';
import ImagePicker from 'react-native-image-picker';
export default class Mapview extends React.Component {
constructor(props) {
super(props);
this.state = {
latitude: 0,
longitude: 0,
error: null,
coords: [],
places: null,
selectedLat: "",
selectedLang: "",
distance: "",
tourStatus: false,
};
}
getLocation = () => {
Geolocation.getCurrentPosition(position => {
this.setState({ latitude: position.coords.latitude })
this.setState({ longitude: position.coords.longitude })
}
);
}
setLatLang = (lat, lng) => {
this.setState({ selectedLat: lat })
this.setState({ selectedLang: lng })
}
showCoords() {
const arrayMarkers = [];
var coordsLatLang = [];
var allCoords = [];
var selectedCoordLat = [];
var selectedCoordLang = [];
var dis = [];
Geolocation.getCurrentPosition(position => {
var userLat = position.coords.latitude
var userLang = position.coords.longitude
for (let index = 0; index < this.props.locCoord.length; index++) {
coordsLatLang = this.props.locCoord[index].split(',')
allCoords.push(this.props.locCoord[index].split(','))
selectedCoordLat.push(allCoords[index][0])
selectedCoordLang.push(allCoords[index][1])
dis.push(getDistance(
{ latitude: userLat, longitude: userLang },
{ latitude: selectedCoordLat[index], longitude: selectedCoordLang[index] }
))
var lat = coordsLatLang[0]
var lng = coordsLatLang[1]
arrayMarkers.push(
< Marker
pinColor={'#24012f'}
coordinate={{
latitude: Number(lat),
longitude: Number(lng),
}}
>
<Callout tooltip style={{ position: 'relative' }} onPress={() => {
Actions.ShowInfo({ rating: this.props.rating, locID: this.props.locID, images: this.state.imgLink, tourName: this.props.name, info: this.props.info }) // The Code I'm Redirecting
}} >
<LinearGradient start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={{ borderRadius: 20 }} colors={['#531c5c', '#4b5cab']}>
<View style={{ flexDirection: 'column', alignContent: 'center', alignItems: 'center', flex: 1, padding: 15 }}>
<Text style={{ color: "white", fontWeight: 'bold', fontSize: 20 }}>{this.props.locNames[index]}</Text>
<Text style={{ marginTop: 5, color: "white" }}>Puanı:{this.props.TourLocRating[index].toFixed(2)}</Text>
<Text style={{ color: "white" }}>Mesafe:{(dis[index] / 1000).toFixed(2)}KM</Text>
<Text style={{ marginTop: 5, color: "white", marginBottom: 5 }}>Rota Oluşturmak İçin Tıklayın!</Text>
</View>
</LinearGradient>
</Callout>
</Marker >
)
}
}
)
this.setState({ places: arrayMarkers })
}
openCam() {
ImagePicker.launchCamera((response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
this.setState({
avatarSource: source,
});
}
});
}
componentWillMount() {
this.showCoords();
}
componentDidMount() {
this.getLocation();
}
render() {
console.log(this.props.images)
return (
<View style={{ flex: 1 }}>
<View style={{
backgroundColor: 'white',
alignItems: 'center',
width: width,
height: height * 0.08,
fontWeight: "bold",
flexDirection: 'row',
justifyContent: 'flex-start',
}}>
<TouchableOpacity onPress={() => { this.props.navigation.goBack() }}>
<Image
style={{ width: width * 0.05, height: height * 0.03, marginTop: 15, marginBottom: 10, marginLeft: 5 }}
source={require('../../img/back.png')}
/>
</TouchableOpacity>
<Image resizeMode="contain" style={{ marginLeft: width * 0.17 }}
source={require('../../img/headerText.png')}
/>
</View>
<View style={[styles.lineFooterStyle]} />
<MapView
provider={PROVIDER_GOOGLE}
region={{
latitude: this.state.latitude,
longitude: this.state.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
showsUserLocation={true}
style={{ flex: 1 }}
>
{this.state.places}
<MapViewDirections
precision={"high"}
origin={{ latitude: this.state.latitude, longitude: this.state.longitude }}
destination={{ latitude: this.state.selectedLat, longitude: this.state.selectedLang }}
apikey={'AIzaSyAYGO8DoGtW-v8lEdDbtagGNp5ogtAA8ok'}
strokeWidth={6}
strokeColor="#531959"
/>
</MapView>
<View>
<TouchableOpacity style={{ width: width * 0.2, height: width * 0.2, marginTop: -height * 0.17, marginLeft: width * 0.4 }} onPress={() => this.openCam()}>
<Image style={{ width: width * 0.2, height: width * 0.2, marginTop: 15, borderRadius: 25 }}
source={require('../../img/ARLogo.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.lineFooterStyle} />
<View style={styles.footerStyle}>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Mainpage")}>
<Image style={styles.navItemHomeStyle}
source={require('../../img/Home.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Discover")}>
<Image style={styles.navItemBookmarkStyle}
source={require('../../img/Bookmark_2.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("MyProfile")}>
<Image style={styles.navItemProfileStyle}
source={require('../../img/Profile.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}
ShowInfo.js Code Text
import React from 'react';
import { Actions } from 'react-native-router-flux';
import {
StyleSheet,
Text,
ScrollView,
Image,
View,
Dimensions,
TouchableOpacity,
TextInput
} from 'react-native';
import { AirbnbRating, Rating } from 'react-native-ratings';
import LinearGradient from 'react-native-linear-gradient';
import * as firebase from 'firebase';
import { SliderBox } from "react-native-image-slider-box";
const { width, height } = Dimensions.get('window');
import Comment from '../HorizontalSlider/Comment';
let userRef = db.ref('/Users');
let commentsRef = db.ref('/LocationComments');
let locationRef = db.ref('/Location');
import { db } from '../../components/dbConfig/config';
if (!firebase.apps.length) {
firebase.initializeApp(db);
}
const rootRef = firebase.database().ref();
const loccommentRef = rootRef.child('LocationComments');
let addItem = (comment, locationID, userName, rating, comments, locID) => {
loccommentRef.push({
comment: comment,
LocationID: locationID,
username: userName,
users: [],
rating: rating
});
var count = 0;
var newRating = 0;
for (let index = 0; index < comments.length; index++) {
if (locID == comments[index].LocationID) {
count++;
newRating += comments[index].rating
}
}
var generalNewRating = (newRating + rating - 1) / count
locationRef.child(locID).update({ 'Rating': generalNewRating })
};
export default class ShowInfo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
locInfo: [],
comments: [],
comment: '',
userName: '',
userEmail: '',
rating: '',
users: [],
};
}
ratingCompleted = (rating) => {
this.setState({ rating: rating })
}
getUserData() {
userRef.on('value', snapshot => {
let data = snapshot.val();
let users = Object.values(data);
this.setState({ users: users });
});
}
getComments() {
commentsRef.on('value', snapshot => {
let data = snapshot.val();
let comments = Object.values(data);
this.setState({ comments: comments });
});
}
getLocationData() {
locationRef.on('value', snapshot => {
let data = snapshot.val();
let locInfo = Object.values(data);
this.setState({ locInfo: locInfo });
});
}
getUserName = () => {
for (let index = 0; index < this.state.users.length; index++) {
if (this.props.userEmail == this.state.users[index].email) {
return this.state.users[index].username;
}
}
}
updateRating = () => {
var count = 0;
for (let index = 0; index < this.state.comments.length; index++) {
if (this.props.locID == this.state.comments[index].LocationID) {
count++;
}
}
locationRef.child(this.props.locID).update({ 'Rating': (this.state.locInfo[this.props.locID].Rating + this.state.rating) / count })
}
componentWillMount() {
this.getLocationData()
this.getUserData()
this.getComments()
}
inRender(images, commentContext, comments, locCoord, locNames) {
console.log(this.state.locInfo[2].Rating, "---")
if (this.getUserName() != null) {
this.setState({ userName: this.getUserName() })
}
for (let index = 0; index < this.state.locInfo.length; index++) {
if (this.props.locID == this.state.locInfo[index].ID) {
images = this.state.locInfo[index].Image.split(',')
locCoord.push(this.state.locInfo[index].Coordinate)
console.log(locCoord)
locNames.push(this.state.locInfo[index].Name)
}
}
for (let index = 0; index < this.state.comments.length; index++) {
if (this.props.locID == this.state.comments[index].LocationID) {
comments.push(this.state.comments[index])
}
}
for (let index = 0; index < comments.length; index++) {
if (comments[index].username != "") {
commentContext.push(
<Comment
username={comments[index].username}
comment={comments[index].comment}
rating={comments[index].rating}
/>
)
}
}
return images;
}
render() {
var locNames = [];
var images = [];
var comments = [];
var commentContext = [];
var locCoord = []
var retImages = this.inRender(images, commentContext, comments, locCoord, locNames);
var TourLocRating = [];
TourLocRating.push(this.props.rating)
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<View style={{
backgroundColor: 'white',
alignItems: 'center',
width: width,
height: height * 0.08,
fontWeight: "bold",
flexDirection: 'row',
justifyContent: 'flex-start',
}}>
<TouchableOpacity onPress={() => { this.props.navigation.goBack() }}>
<Image
style={{ width: width * 0.05, height: height * 0.03, marginTop: 15, marginBottom: 10, marginLeft: 5 }}
source={require('../../img/back.png')}
/>
</TouchableOpacity>
<Image resizeMode="contain" style={{ marginLeft: width * 0.17 }}
source={require('../../img/headerText.png')}
/>
</View>
<View style={[styles.lineFooterStyle]} />
<ScrollView>
<SliderBox
style={{ height: height * 0.4, marginLeft: 5, marginRight: 5 }}
imageLoadingColor="white"
dotColor="white"
inactiveDotColor="#90A4AE"
autoplay
disableOnPress
circleLoop
images={retImages}
//currentImageEmitter={index => locName=imgSliderHolder[index].Name} //Resim üzerinde lokasyonun adını gösterebilirsin. Resim geldiğinde gerçekleşen func.
//onCurrentImagePressed={index => Actions.ShowInfo({ locImage: images[index], tourName: imgSliderHolder[index].Name, info: imgSliderHolder[index].Info })}
/>
<View style={{ marginLeft: 15 }}>
<View style={{ flexDirection: 'row' }}>
<View style={{ flexDirection: 'column' }}>
<View style={{ marginTop: 30 }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginLeft: height * 0.01 }}>{this.props.tourName}</Text>
<LinearGradient style={styles.gradientLineStyle} start={{ x: 0, y: 1 }} end={{ x: 1, y: 1 }} colors={['#3E276F', '#F9F7F6']}></LinearGradient>
</View>
<TouchableOpacity style={styles.BtnStyleLogin} onPress={() => Actions.LocMapview({ locCoord: locCoord, locNames, kind: "location", TourLocRating })}>
<Text style={{ color: 'white' }}>
Başla
</Text>
</TouchableOpacity>
<View style={{ flexDirection: 'row' }}>
<Rating
readonly={true}
startingValue={this.props.rating}
style={{ paddingVertical: 10 }}
imageSize={20}
/>
<Text style={{ marginLeft: width * 0.02, marginBottom: height * 0.015, marginTop: height * 0.012, fontWeight: 'bold' }}>Puanı:{this.props.rating.toFixed(2)}</Text>
</View>
</View>
<TouchableOpacity onPress={() => this.playSound()}>
<Image style={{ width: 40, height: 40, marginTop: height * 0.1, }}
source={require('../../img/sound_button.png')}
/>
</TouchableOpacity>
</View>
<View style={{ flexDirection: 'row', marginBottom: 15, marginTop: 15, justifyContent: 'space-between' }}>
<TouchableOpacity onPress={() => { this.refs._scrollView.scrollTo(); }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginLeft: height * 0.025 }}>Hakkında</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => { this.refs._scrollView.scrollTo({ x: width, y: 0 }); }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginRight: 15 }}>Değerlendir</Text>
</TouchableOpacity>
</View>
<LinearGradient style={styles.gradientLineStyle} start={{ x: 0, y: 1 }} end={{ x: 1, y: 1 }} colors={['#3E276F', '#F9F7F6']}></LinearGradient>
</View>
<ScrollView
ref='_scrollView'
horizontal={true}
pagingEnabled={true}
>
<View style={{
flex: 1,
width: width,
}}>
<Text style={{ padding: 15, textAlign: 'justify' }}>{this.props.info}</Text>
</View>
<View
style={{
flex: 1,
width: width,
padding: 15
}}>
<TextInput
style={{ height: 150, borderColor: 'gray', borderWidth: 0.5, borderRadius: 25 }}
multiline={true}
onChangeText={comment => this.setState({ comment })}
/>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<View style={{ marginTop: 20 }}>
<AirbnbRating
count={5}
showRating={false}
onFinishRating={this.ratingCompleted}
defaultRating={0}
size={30}
fractions={2}
/>
</View>
<TouchableOpacity style={{
width: width * 0.3,
height: height * 0.06,
marginTop: 15,
marginBottom: 15,
borderRadius: 15,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#1a345c',
flexDirection: 'row',
}} onPress={() => addItem(this.state.comment, this.props.locID, this.state.userName, this.state.rating, this.state.comments, this.props.locID)}>
<Text style={{ color: 'white' }}>
Değerlendir
</Text>
</TouchableOpacity>
</View>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 25, marginTop: 15 }}>Yorumlar</Text>
{commentContext}
</View>
</ScrollView>
</ScrollView>
<View style={styles.lineFooterStyle} />
<View style={styles.footerStyle}>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Mainpage")}>
<Image style={styles.navItemHomeStyle}
source={require('../../img/Home.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Discover")}>
<Image style={styles.navItemBookmarkStyle}
source={require('../../img/Bookmark_2.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("MyProfile")}>
<Image style={styles.navItemProfileStyle}
source={require('../../img/Profile.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}

TypeError: undefined is not an object ( evaluating 'this.state.locInfo[index].Images.split')

When I click the map in React-native, I am trying to redirect. But I'm getting an error. mapview.js => I'm redirecting ShowInfo.js.
The code I'm redirecting to:
ShowInfo.js
Actions.ShowInfo({ rating: this.props.rating, locID: this.props.locID, images: this.state.imgLink, tourName: this.props.name, info: this.props.info }) // The Code I'm Redirecting
Mapview.js Code Text
import React from 'react';
//import {View, Text} from 'react-native';
import { getDistance, getPreciseDistance } from 'geolib';
import MapView, { Marker, PROVIDER_GOOGLE, Callout } from 'react-native-maps';
import Geolocation from '#react-native-community/geolocation';
import { Actions } from 'react-native-router-flux';
import {
StyleSheet,
Image,
View,
Dimensions,
TouchableOpacity,
Text,
} from 'react-native';
const { width, height } = Dimensions.get('window');
import LinearGradient from 'react-native-linear-gradient';
import MapViewDirections from 'react-native-maps-directions';
import ImagePicker from 'react-native-image-picker';
export default class Mapview extends React.Component {
constructor(props) {
super(props);
this.state = {
latitude: 0,
longitude: 0,
error: null,
coords: [],
places: null,
selectedLat: "",
selectedLang: "",
distance: "",
tourStatus: false,
};
}
getLocation = () => {
Geolocation.getCurrentPosition(position => {
this.setState({ latitude: position.coords.latitude })
this.setState({ longitude: position.coords.longitude })
}
);
}
setLatLang = (lat, lng) => {
this.setState({ selectedLat: lat })
this.setState({ selectedLang: lng })
}
showCoords() {
const arrayMarkers = [];
var coordsLatLang = [];
var allCoords = [];
var selectedCoordLat = [];
var selectedCoordLang = [];
var dis = [];
Geolocation.getCurrentPosition(position => {
var userLat = position.coords.latitude
var userLang = position.coords.longitude
for (let index = 0; index < this.props.locCoord.length; index++) {
coordsLatLang = this.props.locCoord[index].split(',')
allCoords.push(this.props.locCoord[index].split(','))
selectedCoordLat.push(allCoords[index][0])
selectedCoordLang.push(allCoords[index][1])
dis.push(getDistance(
{ latitude: userLat, longitude: userLang },
{ latitude: selectedCoordLat[index], longitude: selectedCoordLang[index] }
))
var lat = coordsLatLang[0]
var lng = coordsLatLang[1]
arrayMarkers.push(
< Marker
pinColor={'#24012f'}
coordinate={{
latitude: Number(lat),
longitude: Number(lng),
}}
>
<Callout tooltip style={{ position: 'relative' }} onPress={() => {
Actions.ShowInfo({ rating: this.props.rating, locID: this.props.locID, images: this.state.imgLink, tourName: this.props.name, info: this.props.info }) // The Code I'm Redirecting
}} >
<LinearGradient start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={{ borderRadius: 20 }} colors={['#531c5c', '#4b5cab']}>
<View style={{ flexDirection: 'column', alignContent: 'center', alignItems: 'center', flex: 1, padding: 15 }}>
<Text style={{ color: "white", fontWeight: 'bold', fontSize: 20 }}>{this.props.locNames[index]}</Text>
<Text style={{ marginTop: 5, color: "white" }}>Puanı:{this.props.TourLocRating[index].toFixed(2)}</Text>
<Text style={{ color: "white" }}>Mesafe:{(dis[index] / 1000).toFixed(2)}KM</Text>
<Text style={{ marginTop: 5, color: "white", marginBottom: 5 }}>Rota Oluşturmak İçin Tıklayın!</Text>
</View>
</LinearGradient>
</Callout>
</Marker >
)
}
}
)
this.setState({ places: arrayMarkers })
}
openCam() {
ImagePicker.launchCamera((response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
this.setState({
avatarSource: source,
});
}
});
}
componentWillMount() {
this.showCoords();
}
componentDidMount() {
this.getLocation();
}
render() {
console.log(this.props.images)
return (
<View style={{ flex: 1 }}>
<View style={{
backgroundColor: 'white',
alignItems: 'center',
width: width,
height: height * 0.08,
fontWeight: "bold",
flexDirection: 'row',
justifyContent: 'flex-start',
}}>
<TouchableOpacity onPress={() => { this.props.navigation.goBack() }}>
<Image
style={{ width: width * 0.05, height: height * 0.03, marginTop: 15, marginBottom: 10, marginLeft: 5 }}
source={require('../../img/back.png')}
/>
</TouchableOpacity>
<Image resizeMode="contain" style={{ marginLeft: width * 0.17 }}
source={require('../../img/headerText.png')}
/>
</View>
<View style={[styles.lineFooterStyle]} />
<MapView
provider={PROVIDER_GOOGLE}
region={{
latitude: this.state.latitude,
longitude: this.state.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
showsUserLocation={true}
style={{ flex: 1 }}
>
{this.state.places}
<MapViewDirections
precision={"high"}
origin={{ latitude: this.state.latitude, longitude: this.state.longitude }}
destination={{ latitude: this.state.selectedLat, longitude: this.state.selectedLang }}
apikey={'AIzaSyAYGO8DoGtW-v8lEdDbtagGNp5ogtAA8ok'}
strokeWidth={6}
strokeColor="#531959"
/>
</MapView>
<View>
<TouchableOpacity style={{ width: width * 0.2, height: width * 0.2, marginTop: -height * 0.17, marginLeft: width * 0.4 }} onPress={() => this.openCam()}>
<Image style={{ width: width * 0.2, height: width * 0.2, marginTop: 15, borderRadius: 25 }}
source={require('../../img/ARLogo.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.lineFooterStyle} />
<View style={styles.footerStyle}>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Mainpage")}>
<Image style={styles.navItemHomeStyle}
source={require('../../img/Home.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Discover")}>
<Image style={styles.navItemBookmarkStyle}
source={require('../../img/Bookmark_2.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("MyProfile")}>
<Image style={styles.navItemProfileStyle}
source={require('../../img/Profile.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}
ShowInfo.js Code Text
import React from 'react';
import { Actions } from 'react-native-router-flux';
import {
StyleSheet,
Text,
ScrollView,
Image,
View,
Dimensions,
TouchableOpacity,
TextInput
} from 'react-native';
import { AirbnbRating, Rating } from 'react-native-ratings';
import LinearGradient from 'react-native-linear-gradient';
import * as firebase from 'firebase';
import { SliderBox } from "react-native-image-slider-box";
const { width, height } = Dimensions.get('window');
import Comment from '../HorizontalSlider/Comment';
let userRef = db.ref('/Users');
let commentsRef = db.ref('/LocationComments');
let locationRef = db.ref('/Location');
import { db } from '../../components/dbConfig/config';
if (!firebase.apps.length) {
firebase.initializeApp(db);
}
const rootRef = firebase.database().ref();
const loccommentRef = rootRef.child('LocationComments');
let addItem = (comment, locationID, userName, rating, comments, locID) => {
loccommentRef.push({
comment: comment,
LocationID: locationID,
username: userName,
users: [],
rating: rating
});
var count = 0;
var newRating = 0;
for (let index = 0; index < comments.length; index++) {
if (locID == comments[index].LocationID) {
count++;
newRating += comments[index].rating
}
}
var generalNewRating = (newRating + rating - 1) / count
locationRef.child(locID).update({ 'Rating': generalNewRating })
};
export default class ShowInfo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
locInfo: [],
comments: [],
comment: '',
userName: '',
userEmail: '',
rating: '',
users: [],
};
}
ratingCompleted = (rating) => {
this.setState({ rating: rating })
}
getUserData() {
userRef.on('value', snapshot => {
let data = snapshot.val();
let users = Object.values(data);
this.setState({ users: users });
});
}
getComments() {
commentsRef.on('value', snapshot => {
let data = snapshot.val();
let comments = Object.values(data);
this.setState({ comments: comments });
});
}
getLocationData() {
locationRef.on('value', snapshot => {
let data = snapshot.val();
let locInfo = Object.values(data);
this.setState({ locInfo: locInfo });
});
}
getUserName = () => {
for (let index = 0; index < this.state.users.length; index++) {
if (this.props.userEmail == this.state.users[index].email) {
return this.state.users[index].username;
}
}
}
updateRating = () => {
var count = 0;
for (let index = 0; index < this.state.comments.length; index++) {
if (this.props.locID == this.state.comments[index].LocationID) {
count++;
}
}
locationRef.child(this.props.locID).update({ 'Rating': (this.state.locInfo[this.props.locID].Rating + this.state.rating) / count })
}
componentWillMount() {
this.getLocationData()
this.getUserData()
this.getComments()
}
inRender(images, commentContext, comments, locCoord, locNames) {
console.log(this.state.locInfo[2].Rating, "---")
if (this.getUserName() != null) {
this.setState({ userName: this.getUserName() })
}
for (let index = 0; index < this.state.locInfo.length; index++) {
if (this.props.locID == this.state.locInfo[index].ID) {
images = this.state.locInfo[index].Image.split(',')
locCoord.push(this.state.locInfo[index].Coordinate)
console.log(locCoord)
locNames.push(this.state.locInfo[index].Name)
}
}
for (let index = 0; index < this.state.comments.length; index++) {
if (this.props.locID == this.state.comments[index].LocationID) {
comments.push(this.state.comments[index])
}
}
for (let index = 0; index < comments.length; index++) {
if (comments[index].username != "") {
commentContext.push(
<Comment
username={comments[index].username}
comment={comments[index].comment}
rating={comments[index].rating}
/>
)
}
}
return images;
}
render() {
var locNames = [];
var images = [];
var comments = [];
var commentContext = [];
var locCoord = []
var retImages = this.inRender(images, commentContext, comments, locCoord, locNames);
var TourLocRating = [];
TourLocRating.push(this.props.rating)
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<View style={{
backgroundColor: 'white',
alignItems: 'center',
width: width,
height: height * 0.08,
fontWeight: "bold",
flexDirection: 'row',
justifyContent: 'flex-start',
}}>
<TouchableOpacity onPress={() => { this.props.navigation.goBack() }}>
<Image
style={{ width: width * 0.05, height: height * 0.03, marginTop: 15, marginBottom: 10, marginLeft: 5 }}
source={require('../../img/back.png')}
/>
</TouchableOpacity>
<Image resizeMode="contain" style={{ marginLeft: width * 0.17 }}
source={require('../../img/headerText.png')}
/>
</View>
<View style={[styles.lineFooterStyle]} />
<ScrollView>
<SliderBox
style={{ height: height * 0.4, marginLeft: 5, marginRight: 5 }}
imageLoadingColor="white"
dotColor="white"
inactiveDotColor="#90A4AE"
autoplay
disableOnPress
circleLoop
images={retImages}
//currentImageEmitter={index => locName=imgSliderHolder[index].Name} //Resim üzerinde lokasyonun adını gösterebilirsin. Resim geldiğinde gerçekleşen func.
//onCurrentImagePressed={index => Actions.ShowInfo({ locImage: images[index], tourName: imgSliderHolder[index].Name, info: imgSliderHolder[index].Info })}
/>
<View style={{ marginLeft: 15 }}>
<View style={{ flexDirection: 'row' }}>
<View style={{ flexDirection: 'column' }}>
<View style={{ marginTop: 30 }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginLeft: height * 0.01 }}>{this.props.tourName}</Text>
<LinearGradient style={styles.gradientLineStyle} start={{ x: 0, y: 1 }} end={{ x: 1, y: 1 }} colors={['#3E276F', '#F9F7F6']}></LinearGradient>
</View>
<TouchableOpacity style={styles.BtnStyleLogin} onPress={() => Actions.LocMapview({ locCoord: locCoord, locNames, kind: "location", TourLocRating })}>
<Text style={{ color: 'white' }}>
Başla
</Text>
</TouchableOpacity>
<View style={{ flexDirection: 'row' }}>
<Rating
readonly={true}
startingValue={this.props.rating}
style={{ paddingVertical: 10 }}
imageSize={20}
/>
<Text style={{ marginLeft: width * 0.02, marginBottom: height * 0.015, marginTop: height * 0.012, fontWeight: 'bold' }}>Puanı:{this.props.rating.toFixed(2)}</Text>
</View>
</View>
<TouchableOpacity onPress={() => this.playSound()}>
<Image style={{ width: 40, height: 40, marginTop: height * 0.1, }}
source={require('../../img/sound_button.png')}
/>
</TouchableOpacity>
</View>
<View style={{ flexDirection: 'row', marginBottom: 15, marginTop: 15, justifyContent: 'space-between' }}>
<TouchableOpacity onPress={() => { this.refs._scrollView.scrollTo(); }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginLeft: height * 0.025 }}>Hakkında</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => { this.refs._scrollView.scrollTo({ x: width, y: 0 }); }}>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 15, marginRight: 15 }}>Değerlendir</Text>
</TouchableOpacity>
</View>
<LinearGradient style={styles.gradientLineStyle} start={{ x: 0, y: 1 }} end={{ x: 1, y: 1 }} colors={['#3E276F', '#F9F7F6']}></LinearGradient>
</View>
<ScrollView
ref='_scrollView'
horizontal={true}
pagingEnabled={true}
>
<View style={{
flex: 1,
width: width,
}}>
<Text style={{ padding: 15, textAlign: 'justify' }}>{this.props.info}</Text>
</View>
<View
style={{
flex: 1,
width: width,
padding: 15
}}>
<TextInput
style={{ height: 150, borderColor: 'gray', borderWidth: 0.5, borderRadius: 25 }}
multiline={true}
onChangeText={comment => this.setState({ comment })}
/>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<View style={{ marginTop: 20 }}>
<AirbnbRating
count={5}
showRating={false}
onFinishRating={this.ratingCompleted}
defaultRating={0}
size={30}
fractions={2}
/>
</View>
<TouchableOpacity style={{
width: width * 0.3,
height: height * 0.06,
marginTop: 15,
marginBottom: 15,
borderRadius: 15,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#1a345c',
flexDirection: 'row',
}} onPress={() => addItem(this.state.comment, this.props.locID, this.state.userName, this.state.rating, this.state.comments, this.props.locID)}>
<Text style={{ color: 'white' }}>
Değerlendir
</Text>
</TouchableOpacity>
</View>
<Text style={{ color: '#171c69', fontWeight: 'bold', fontSize: 25, marginTop: 15 }}>Yorumlar</Text>
{commentContext}
</View>
</ScrollView>
</ScrollView>
<View style={styles.lineFooterStyle} />
<View style={styles.footerStyle}>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Mainpage")}>
<Image style={styles.navItemHomeStyle}
source={require('../../img/Home.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("Discover")}>
<Image style={styles.navItemBookmarkStyle}
source={require('../../img/Bookmark_2.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.styleInBottombar} onPress={() => this.props.navigation.navigate("MyProfile")}>
<Image style={styles.navItemProfileStyle}
source={require('../../img/Profile.png')}
/>
</TouchableOpacity>
</View>
</View>
);
}
}

How to Implement Assist user to accurately navigate through shortest path to particular location in any place

1.Need to show User Current Location
2.OnSelect of particular destination , Need to Show a Progress Line
3.On Movement of user towards destination the Map Marker should move along with the User.
Hi check out the full code on the follow link:
https://snack.expo.io/#matheus_cbrl/maps-geoloation-uber
Here bellow some code:
import React, { Component, Fragment } from "react";
import {
Platform,
StyleSheet,
Text,
View,
Alert,
ScrollView,
Image,
Dimensions,
TouchableOpacity,
StatusBar,
AsyncStorage,
BackHandler,
} from 'react-native';
import { getPixelSize } from '../utils';
import MapView, { Marker } from "react-native-maps";
import Geocoder from "react-native-geocoding";
import markerImage2 from '../assets/bus-stop(1).png';
import markerImage from '../assets/placeholder(2).png';
import AwesomeAlert from 'react-native-awesome-alerts';
import night from '../assets/placeholder(2).png';
import { FAB } from 'react-native-paper';
import Modal from 'react-native-modal';
import { ContainerTop, TypeDescription, ContainerTab } from './stylesInfo.js';
import Search from './Search/map-input.js';
import Directions from '../Directions';
import Details from "../Details";
import {
Back,
LocationBox,
LocationText,
LocationTimeBox,
LocationTimeText,
LocationTimeTextSmall
} from "./styles.js";
Geocoder.init(" ");
const { width, height } = Dimensions.get('window');
const ASPECT_RATIO = width / height;
const LATITUDE = -29.1684796;
const LONGITUDE = -51.1793861;
const LATITUDE_DELTA = 0.003;
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;
export default class Map extends Component {
state = {
focusedlocation: {
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
},
isLoading: true,
markers: [],
modalVisible: false,
locationChosen: false,
showAlert: false,
initialized: false,
destination: null,
duration: null,
location: null,
region: null,
};
async componentDidMount() {
navigator.geolocation.getCurrentPosition(
async ({ coords: { latitude, longitude } }) => {
const response = await Geocoder.from({ latitude, longitude });
const address = response.results[0].formatted_address;
const location = address.substring(0, address.indexOf(","));
this.setState({
location,
region: {
latitude,
longitude,
latitudeDelta: 0.0143,
longitudeDelta: 0.0134
}
});
}, //sucesso
() => {}, //erro
{
enableHighAccuracy: true, // allows you to get the most accurate location
timeout: 2000, // (milliseconds) in which the app has to wait for location before it throws an error
maximumAge: 1000, // (milliseconds) if a previous location exists in the cache, how old for it to be considered acceptable
distanceFilter: 20, // (meters) how many meters the user has to move before a location update is triggered
}
);
this.getLocationHandler();
//BackHandler.addEventListener(
//'hardwareBackPress',
//this.backpress,
//this.backHandler
//);
return fetch(
'https://gist.githubusercontent.com/MatheusCbrl/bba7db1c0dbc68be2f26d5c7e15649b6/raw/9d10bab16612a0055fff0f14b012e68083e27033/ParadasDiurno.json'
)
.then(response => response.json())
.then(responseJson => {
// just setState here e.g.
this.setState({
markers: responseJson,
isLoading: false,
});
})
.catch(error => {
console.error(error);
});
}
onMapReady = () => {
this.setState({ initialized: true });
};
backpress = () => {
this.setState({ modalVisible: !this.state.modalVisible });
return true;
};
backHandler = () => {
BackHandler.exitApp();
};
handleLocationSelected = (data, { geometry }) => {
const {
location: { lat: latitude, lng: longitude }
} = geometry;
this.setState({
destination: {
latitude,
longitude,
title: data.structured_formatting.main_text
}
});
};
handleBack = () => {
this.setState({ destination: null });
};
pickLocationHandler = event => {
const coords = event.nativeEvent.coordinate;
console.log('Location picker Marker', coords);
this.mapView.animateToRegion({
...this.state.region,
latitude: coords.latitude,
longitude: coords.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
});
this.setState(prevState => {
return {
region: {
...prevState.region,
latitude: coords.latitude,
longitude: coords.longitude,
},
locationChosen: true,
};
});
};
getLocationHandler = () => {
navigator.geolocation.getCurrentPosition(
pos => {
const coordsEvent = {
nativeEvent: {
coordinate: {
latitude: pos.coords.latitude,
longitude: pos.coords.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
},
},
};
this.pickLocationHandler(coordsEvent);
},
err => {console.log(err);
//Alert.alert(' ','Ocorreu um erro ao carregar sua localização, por favor ligue o GPS!');
},
{
enableHighAccuracy: true, // allows you to get the most accurate location
timeout: 20000, // (milliseconds) in which the app has to wait for location before it throws an error
maximumAge: 1000, // (milliseconds) if a previous location exists in the cache, how old for it to be considered acceptable
distanceFilter: 20, // (meters) how many meters the user has to move before a location update is triggered
}
);
};
showAlert = () => {
this.setState({
showAlert: true,
});
};
hideAlert = () => {
this.setState({
showAlert: false,
});
};
renderMarkers() {
return this.state.isLoading
? null
: this.state.markers.map((marker, index) => {
const coords = {
latitude: JSON.parse(marker.latitude),
longitude: JSON.parse(marker.longitude),
};
return (
<Marker
onPress={this.pickLocationHandler}
ref={mark => (marker.mark = mark)}
key={index}
title={'Parada'}
description={marker.hora}
tracksViewChanges={!this.state.initialized}
{...this.props}
pinColor={'tomato'}
coordinate={coords}>
{this.props.children}
</Marker>
);
});
}
_logout = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Menu');
};
render() {
const {showAlert, region, destination, duration, location } = this.state;
return (
<View style={styles.container}>
<StatusBar hidden />
<MapView
rotateEnabled={true}
scrollEnabled={true}
showsMyLocationButton={true}
zoomTapEnabled={true}
zoomControlEnabled={true}
zoomEnabled={true}
showsPointsOfInterest={true}
showBuildings={false}
followsUserLocation={true}
showsUserLocation={true}
clustering={true}
showsTraffic={false}
showsIndoors={false}
loadingEnabled={true}
apType="standard"
provider="google"
onMapReady={this.onMapReady}
style={styles.map}
//region={region}
initialRegion={this.state.focusedlocation}
ref={ref => (this.mapView = ref)}
>
{this.renderMarkers()}
{destination && (
<Fragment>
<Directions
origin={region}
destination={destination}
onReady={result => {
this.setState({ duration: Math.floor(result.duration) });
this.mapView.fitToCoordinates(result.coordinates, {
edgePadding: {
right: getPixelSize(50),
left: getPixelSize(50),
top: getPixelSize(50),
bottom: getPixelSize(200),
}
});
}}
/>
<Marker
onPress={this.pickLocationHandler}
coordinate={destination}
anchor={{ x: 0, y: 0 }}
>
<LocationBox>
<LocationText>{destination.title}</LocationText>
</LocationBox>
</Marker>
<Marker coordinate={region} anchor={{ x: 0, y: 0 }}>
<LocationBox>
<LocationTimeBox>
<LocationTimeText>{duration}</LocationTimeText>
<LocationTimeTextSmall>MIN</LocationTimeTextSmall>
</LocationTimeBox>
<LocationText>{location}</LocationText>
</LocationBox>
</Marker>
</Fragment>
)}
</MapView>
{destination ? (
<Fragment>
<Back onPress={this.handleBack}>
<Image
source={require('../assets/back.png')}
style={{
marginLeft: 1,
marginTop: 1,
width: 25,
height: 25,
tintColor: '#FF3D00',
}}
/>
</Back>
</Fragment>
) : (
<Search onLocationSelected={this.handleLocationSelected} />
)}
<AwesomeAlert
show={showAlert}
showProgress={false}
title="Paradas Diurno"
message="Veja as paradas próximas de você"
closeOnTouchOutside={true}
closeOnHardwareBackPress={false}
showCancelButton={false}
showConfirmButton={true}
cancelText="Tudo Bem"
confirmText="OK"
confirmButtonColor="#FF3D00"
onCancelPressed={() => {
this.hideAlert();
}}
onConfirmPressed={() => {
this.hideAlert();
}}
/>
<ContainerTop>
<TypeDescription> </TypeDescription>
</ContainerTop>
<ContainerTab>
<View style={styles.appbar}>
<TouchableOpacity
onPress={() => this.setState({ isVisible: true })}
style={{ backgroundColor: 'transparent' }}>
<Image
source={require('../assets/menu-button.png')}
style={{
width: 25,
height: 25,
marginLeft: 10,
marginTop: 5,
tintColor: '#FF3D00',
}}
/>
<Text
style={{
marginBottom: 15,
marginLeft: 6,
fontSize: 12,
color: '#FF3D00',
}}>
Menu
</Text>
</TouchableOpacity>
<View>
<TouchableOpacity style={{ backgroundColor: 'transparent' }}>
<Image
source={require('../assets/information.png')}
style={{
width: 25,
height: 25,
marginLeft: 25,
marginTop: 5,
tintColor: '#FF3D00',
}}
/>
<Text
style={{
marginBottom: 15,
marginLeft: 20,
fontSize: 12,
color: '#FF3D00',
}}>
Ajuda
</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity style={{ backgroundColor: 'transparent' }}>
<Image
source={require('../assets/location(1).png')}
style={{
width: 25,
height: 25,
marginLeft: 35,
marginTop: 5,
tintColor: '#FF3D00',
}}
/>
<Text
style={{
marginBottom: 15,
marginLeft: 28,
fontSize: 12,
color: '#FF3D00',
}}>
Linhas
</Text>
</TouchableOpacity>
</View>
</View>
</ContainerTab>
<FAB
style={styles.fab}
icon={night}
theme={{ colors: { accent: '#FF3D00' } }}
/>
<TouchableOpacity
onPress={this.getLocationHandler}
style={styles.fab2}>
<Image
source={require('../assets/gps.png')}
style={{
width: 35,
height: 35,
margin: 10,
tintColor: '#FF3D00',
}}
/>
</TouchableOpacity>
<Modal
isVisible={this.state.isVisible}
style={styles.modalSwipe}
onBackButtonPress={() => this.setState({ isVisible: false })}
onBackdropPress={() => this.setState({ isVisible: false })}
onSwipeComplete={() => this.setState({ isVisible: false })}
onSwipeThreshold={20}
swipeDirection="down">
<View style={{ flex: 1, backgroundColor: '#e5e5e5' }}>
<ScrollView showsVerticalScrollIndicator={false}>
<Text style={styles.paragraphSwipe}>Menu</Text>
<TouchableOpacity>
<Text style={styles.buttonStyleSwipe}>
{' '}
Linhas Saída Diurno{' '}
</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.buttonStyleSwipe}>
{' '}
Linhas Saída Noturno{' '}
</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.buttonStyleSwipe}>
{' '}
Linhas Saída Terceiro e Quarto Turnos{' '}
</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.buttonStyleSwipe}> Tutorial </Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.buttonStyleSwipe}> Sobre </Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.buttonStyleSwipe}> Sair </Text>
</TouchableOpacity>
</ScrollView>
</View>
</Modal>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<View
style={{
width: 300,
height: 120,
backgroundColor: '#FFF',
padding: 20,
borderRadius: 20,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{ fontSize: 20, color: 'black', alignSelf: 'center' }}>
Deseja sair do aplicativo?
</Text>
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity
onPress={() => this.backpress()}
style={{
padding: 10,
marginHorizontal: 10,
backgroundColor: '#99d12a',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
}}>
<Text
style={{
color: 'white',
padding: 5,
alignSelf: 'center',
fontWeight: 'bold',
}}>
VOLTAR
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => this.backHandler()}
style={{
padding: 10,
marginHorizontal: 10,
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
}}>
<Text
style={{ color: '#FFF', padding: 5, fontWeight: 'bold' }}>
SAIR
</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
map: {
width: '100%',
height: '100%',
},
appbar: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: 46,
flexDirection: 'row',
},
fab: {
position: 'absolute',
margin: 16,
right: 0,
bottom: 0,
},
fab2: {
position: 'absolute',
bottom: 250,
height: 55,
width: 55,
borderRadius: 30,
marginLeft: Platform.OS === 'ios' ? 300 : 292,
backgroundColor: 'transparent',
},
paragraphSwipe: {
margin: 12,
fontSize: 14,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
modalSwipe: {
justifyContent: 'flex-start',
backgroundColor: '#e5e5e5',
marginHorizontal: 0,
marginBottom: 0,
marginTop: Platform.OS === 'ios' ? 300 : 300,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
borderTopLeftRadius: 15,
borderTopRightRadius: 15,
overflow: 'hidden',
},
buttonStyleSwipe: {
padding: 7,
margin: 1,
fontWeight: 'bold',
borderRadius: 5,
backgroundColor: '#FF3D00',
color: 'white',
fontSize: 16,
alignItems: 'center',
},
});
Plase pay attention to put your on API_KEY
To follow user location on movement, please follow the next steps:
https://medium.com/quick-code/react-native-location-tracking-14ab2c9e2db8
componentDidMount() {
this.watchID = navigator.geolocation.watchPosition(
position => {
const { coordinate, routeCoordinates, distanceTravelled } = this.state;
const { latitude, longitude } = position.coords;
const newCoordinate = {
latitude,
longitude
};
if (Platform.OS === "android") {
if (this.marker) {
this.marker._component.animateMarkerToCoordinate(
newCoordinate,
500
);
}
} else {
coordinate.timing(newCoordinate).start();
}
this.setState({
latitude,
longitude,
routeCoordinates: routeCoordinates.concat([newCoordinate]),
distanceTravelled:
distanceTravelled + this.calcDistance(newCoordinate),
prevLatLng: newCoordinate
});
},
error => console.log(error),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
}

How to draw an arrow on every polyline segment on react-native-maps

hi i want to draw an arrow every polyline
like this image :
read this post :
How to draw an arrow on every polyline segment on Google Maps V3
this is answer my question but this post for javascript
but i use it and this is my code:
<View style={{ height: hp('50%'), width: wp('100%') }}>
<MapView
provider={PROVIDER_GOOGLE}
onLayout={this.onMapLayout}
style={styles.containerMap}
initialRegion={{
latitude: this.props.data ? this.props.data[0].YPOINT : '',
longitude: this.props.data ? this.props.data[0].XPOINT : '',
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}} >
{this.state.isMapReady && <Polyline
strokeWidth={2}
strokeColor="red"
geodesic={true}
icons={
icon = { path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW },
offset = '100%'
}
coordinates={[...this.props.data.map((value, index) => {
return { latitude: value.YPOINT, longitude: value.XPOINT }
})]}
/>
}
</MapView>
</View>
but when run i get error 'google is not defined'.
UPDATE
this is function :
import React, { Component } from 'react'
import { Text, View, StyleSheet, ScrollView, AsyncStorage, ActivityIndicator, Alert, FlatList } from 'react-native'
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
//import arrowIcon from '../../../assets/images/icon/Arrow/090.ico'
import SegmentedControlTab from "react-native-segmented-control-tab";
import { Dropdown } from 'react-native-material-dropdown';
import { getTraceOfHardware } from '../../../Store/actions';
import { connect } from 'react-redux';
import MapView, { Marker, PROVIDER_GOOGLE, Polyline } from 'react-native-maps';
import Icon from 'react-native-vector-icons/Entypo';
var moment = require('jalali-moment');
let dataDay = [{
value: 'امروز',
}, {
value: 'یک روز پیش',
}, {
value: 'دو روز پیش',
}, {
value: 'سه روز پیش',
}, {
value: 'چهار روز پیش',
}, {
value: 'پنج روز پیش',
}, {
value: 'شش روز پیش',
}, {
value: 'هفت روز پیش',
},];
const airplin = <Icon name="aircraft" size={30}/>
class mainRoutsReport extends Component {
constructor () {
super()
this.state = {
selectedIndex: 0,
selectedIndices: [0],
customStyleIndex: 0,
daySelected: '',
isMapReady: false,
tableHead: ['Head', 'Head2', 'Head3', 'Head4', 'Head5', 'Head6', 'Head7', 'Head8', 'Head9'],
widthArr: [40, 60, 80, 100, 120, 140, 160, 180, 200],
data: [],
latlon: []
// tableData: [
// ['1', '2', '3', '4', '5', '6'],
// ['1', '2', '3', '4', '5', '6']
// ]
}
}
//GET UDID
_retrieveUDID = async () => {
try {
return await AsyncStorage.getItem('#IranTracking:UDID', (error, result) => { return result })
} catch (error) {
// Error retrieving data
console.log(error)
}
};
//GET TOKEN
_retrieveToken = async () => {
try {
return await AsyncStorage.getItem('#IranTracking:Token', (error, result) => { return result })
} catch (error) {
// Error retrieving data
console.log(error)
}
};
//This method creat XML to send action.js to get List of Hardware from SOAP
async _makXML(value, index) {
udid = await this._retrieveUDID()
token = await this._retrieveToken()
var yesterday = moment().locale('fa').subtract(index + 0, 'day').format('YYYY-MM-DD')
// console.log(yesterday)
let xml = `<?xml version="1.0" encoding="utf-8"?>\
<x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tra="http://Trackinguri.org/">\
<x:Header>\
<tra:SOAPHeaderContent>\
<tra:UserName></tra:UserName>\
<tra:Password></tra:Password>\
<tra:Token>${token}</tra:Token>\
<tra:UID>${udid}</tra:UID>\
</tra:SOAPHeaderContent>\
</x:Header>\
<x:Body>\
<tra:GetTraceByHardwareID>\
<tra:HardwareID>${this.props.navigation.state.params.HID}</tra:HardwareID>\
<tra:FromDate>${yesterday} 00:00:00</tra:FromDate>\
<tra:ToDate>${yesterday} 23:59:59</tra:ToDate>\
<tra:HijriDates>true</tra:HijriDates>\
<tra:Time_Zone>Tehran</tra:Time_Zone>\
<tra:Lang>fa</tra:Lang>\
</tra:GetTraceByHardwareID>\
</x:Body>\
</x:Envelope>`;
console.log(" xml to get Tarce reports " + xml)
this.props.getTraceOfHardware(xml)
}
componentWillMount() {
this._makXML()
this.props.getTraceOfHardware()
}
componentDidMount() {
}
//this function use for day
_HandelDay(value, index) {
// var yesterday = moment().locale('fa').subtract(index,'day').format('YYYY-MM-DD')
//console.log('index of drop down is : ' + value + ' \nindex is : '+ index + '\n and date is : ' + yesterday)
//Alert.alert(yesterday)
}
handleMultipleIndexSelect = (index: number) => {
const { selectedIndices } = this.state
if (selectedIndices.includes(index)) {
this.setState(prevState => ({
...prevState,
selectedIndices: selectedIndices.filter((i) => i !== index),
}))
} else {
this.setState(prevState => ({
...prevState,
selectedIndices: [
...selectedIndices,
index,
],
}))
}
}
handleCustomIndexSelect = (index: number) => {
this.setState(prevState => ({ ...prevState, customStyleIndex: index }))
}
onMapLayout = () => {
this.setState({ isMapReady: true });
}
_renderItem = ({ item, index }) => (
// console.log(item)
<View style={{ flex: 1, height: hp('15%'), flexDirection: 'row', backgroundColor: index % 2 ? '#f3f3f3' : '#dedede', marginHorizontal: 5, alignItems: 'center' }} >
<View style={{ width: wp('15%'), alignItems: 'center', }}>
<Text style={{ marginLeft: 4, fontFamily: 'IRANSansMobile', }}>{item.TRUCKSTATE}</Text>
</View>
<View style={{ width: wp('12%'), alignItems: 'center' }}>
<Text style={{ marginLeft: 4, fontFamily: 'IRANSansMobile', }}>{item.SPEED}</Text>
</View>
<View style={{ width: wp('50%'), alignItems: 'center' }}>
<Text style={{ marginLeft: 4, fontFamily: 'IRANSansMobile', }}>{item.POSDESCRIPTION}</Text>
</View>
<View style={{ width: wp('10%'), alignItems: 'center' }}>
<Text style={{ marginLeft: 4, fontFamily: 'IRANSansMobile', }}>{item.SENTDATE}</Text>
</View>
<View style={{ width: wp('10%'), alignItems: 'center' }}>
<Text style={{ marginLeft: 4, fontFamily: 'IRANSansMobile', }}>{index + 1}</Text>
</View>
</View>
);
_renderHeadr = () => (
<View style={{ flexDirection: 'row', alignContent: 'space-between', alignItems: 'center', backgroundColor: '#5e9dcb' }}>
<View style={{ borderWidth: 0.5, width: wp('15%'), alignItems: 'center', borderTopLeftRadius: 5 }}>
<Text style={{ fontSize: 15, fontFamily: 'IRANSansMobile', }}>وضعیت</Text>
</View>
<View style={{ borderWidth: 0.5, width: wp('12%'), alignItems: 'center' }}>
<Text style={{ fontSize: 15, fontFamily: 'IRANSansMobile', }}>سرعت</Text>
</View>
<View style={{ borderWidth: 0.5, width: wp('50%'), alignItems: 'center' }}>
<Text style={{ fontSize: 15, fontFamily: 'IRANSansMobile', }}>موقعیت</Text>
</View>
<View style={{ borderWidth: 0.5, width: wp('10%'), alignItems: 'center' }}>
<Text style={{ fontSize: 15, fontFamily: 'IRANSansMobile', }}>زمان</Text>
</View>
<View style={{ borderWidth: 0.5, width: wp('10%'), alignItems: 'center', borderTopRightRadius: 5 }}>
<Text style={{ fontSize: 15, fontFamily: 'IRANSansMobile', }}>ردیف</Text>
</View>
</View>
);
render() {
const { customStyleIndex } = this.state
//console.log(this.props.navigation.state.params.HID)
//console.log(this.props.data)
return (
<View style={{ width: wp('100%'), height: hp('100%') }}>
<Dropdown animationDuration={100}
dropdownMargins={{ min: 0, max: 0 }}
dropdownOffset={{ top: 0, left: 0 }}
style={{ textAlign: 'center' }}
containerStyle={{ textAlign: 'right', backgroundColor: '#fcee97', borderWidth: 0.5, borderRadius: 13, margin: 8 }}
absoluteRTLLayout={true}
data={dataDay}
dropdownPosition={-5}
onChangeText={(value, index) => this._makXML(value, index)}
value={dataDay[0].value} />
<SegmentedControlTab
values={['نمایش متنی', 'نمایش نقشه']}
selectedIndex={customStyleIndex}
onTabPress={this.handleCustomIndexSelect}
borderRadius={0}
tabsContainerStyle={{ height: 50, backgroundColor: '#F2F2F2' }}
tabStyle={{ backgroundColor: '#ffffff', borderWidth: 0, borderColor: 'transparent' }}
activeTabStyle={{ backgroundColor: '#5e9dcb', marginTop: 2 }}
tabTextStyle={{ color: '#000000', fontWeight: 'bold', fontFamily: 'IRANSansMobile' }}
activeTabTextStyle={{ color: '#ffffff', fontFamily: 'IRANSansMobile' }}
/>
{//table
customStyleIndex === 0
&&
<View style={{ paddingBottom: wp('20%') }}>
{this.props.isLoading ? <ActivityIndicator /> : <FlatList
ListHeaderComponent={this._renderHeadr}
stickyHeaderIndices={[0]}
data={this.props.data}
renderItem={this._renderItem}//({item})=>(this._renderItem)
keyExtractor={(item, index) => index.toString()}
/>}
</View>
}
{//Map
customStyleIndex === 1
&&
<View style={{ height: hp('50%'), width: wp('100%') }}>
<MapView
provider={PROVIDER_GOOGLE}
onLayout={this.onMapLayout}
style={styles.containerMap}
initialRegion={{
latitude: this.props.data ? this.props.data[0].YPOINT : '',
longitude: this.props.data ? this.props.data[0].XPOINT : '',
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}} >
{this.state.isMapReady &&
<Polyline
strokeWidth={2}
strokeColor="red"
geodesic={true}
icons={
icon = {airplin },
offset = '100%'
}
coordinates={[...this.props.data.map((value, index) => {
return { latitude: value.YPOINT, longitude: value.XPOINT }
})]}
/>
}
</MapView>
</View>
}
</View>
)
}
}
function mapStateToProps(state) {
console.log(state)
return {
data: state.GetTraceHardware.data,
isLoading: state.GetTraceHardware.isLoading,
error: state.GetTraceHardware.error
}
}
function mapDispatchToProps(dispatch) {
return {
getTraceOfHardware: (data) => dispatch(getTraceOfHardware(data))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(mainRoutsReport);