Reputation: 827
I have some issues with Firebase in React Native.
I'm tried to read the data from the Realtime database. I get the data from database and set them into the state and my initial state is empty, like this
this.state = {
providers: []
}
So now when I log the state in the console I see all of the data very well,
but when I go back to Home screen or reloading app then returns to the same screen I can't see any update in the state Provider and the console is clear that's mean the Array is empty,
so what this does mean! I think the code is right?
Here is my Code:
import React, { Component } from 'react';
import MapView, { Marker } from 'react-native-maps';
import firebase from "react-native-firebase";
// import * as turf from '@turf/turf';
import * as turf from "@turf/turf";
import { View, Text, StyleSheet, Dimensions, PermissionsAndroid, Image } from 'react-native';
let { width, height } = Dimensions.get('window');
const LATITUDE = 50.78825;
const LONGITUDE = 40.4324;
const LATITUDE_DELTA = 0.0922;
const LONGITUDE_DELTA = 0.0421;
class Map extends Component {
constructor(props) {
super(props);
this.state = {
nearest: [],
currentUser: null,
error: null,
width: width,
marginBottom: 1,
region: {
longitude: LONGITUDE,
latitude: LATITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
},
providers: [],
providerObj: [],
distance: null,
};
}
componentDidMount = () => {
this.requestLocationPermission();
this.handleProvider();
};
// Get All Provider in Db
handleProvider = () => {
console.log("The function is called but can't retrieve the data!");
const providerRef = firebase.database().ref('providers');
providerRef.once('value').then(snapshot => {
// console.log(snapshot.val());
console.log("TEST!!")
let newState = [];
snapshot.forEach(async (childSnapshot) => {
console.log("The function is the data!");
await newState.push({
id: childSnapshot.val().id,
username: childSnapshot.val().username,
coordinates: {
longitude: childSnapshot.val().coordinates.longitude,
latitude: childSnapshot.val().coordinates.latitude,
}
});
});
this.setState({ providers: newState }, () => { this.handleNearby() })
});
}
// first one of nearest provider
handleNearby = () => {
const { region, providers } = this.state;
let points = providers.map(p => turf.point([p.coordinates.longitude, p.coordinates.latitude]));
let collection = turf.featureCollection(points);
let currentPoint = turf.point([region.longitude, region.latitude]);
let nearestPoint = turf.nearestPoint(currentPoint, collection);
// let addToMap = [currentPoint, points, nearestPoint];
this.setState({ nearest: nearestPoint }, () => console.log(this.state.nearest));
// console.log(Math.floor(nearest.properties.distanceToPoint));
// console.log(addToMap);
}
// Get User Location
requestLocationPermission = async () => {
const LocationPermission = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
// , {
// 'title': 'Location Access Required',
// 'message': 'This App needs to Access your location'
// }
)
if (LocationPermission === PermissionsAndroid.RESULTS.GRANTED) {
//To Check, If Permission is granted
await navigator.geolocation.getCurrentPosition(
//Will give you the current location
position => {
const longitude = position.coords.longitude;
const latitude = position.coords.latitude;
this.setState({
...this.state.region,
region: {
longitude,
latitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}
},
() => {
this.handleCurrentUserLocation();
// this.handleProvider();
}
);
},
error => console.log(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
this.watchID = navigator.geolocation.watchPosition(position => {
//Will give you the location on location change
// console.log(position);
//getting the Longitude from the location
const longitude = position.coords.longitude;
//getting the Latitude from the location
const latitude = position.coords.latitude;
//Setting state Latitude & Longitude to re re-render the Longitude Text
// this.setState({
// region: {
// latitude,
// longitude,
// latitudeDelta: LATITUDE_DELTA,
// longitudeDelta: LONGITUDE_DELTA,
// }
this.setState({
...this.state.region,
region: {
longitude,
latitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}
}, () => this.handleCurrentUserLocation());
});
}
}
// Save own Location in database
handleCurrentUserLocation = () => {
const { region } = this.state;
const currentUser = firebase.auth().currentUser;
this.setState({ currentUser });
firebase.database().ref("users/" + currentUser.uid).update({
location: {
longitude: region.longitude,
latitude: region.latitude,
}
});
}
render() {
// console.log(this.state.nearest.geometry.coordinates)
const { region, providers } = this.state;
return (
<View style={styles.container} >
<MapView
style={[styles.map, { width: this.state.width }]}
style={StyleSheet.absoluteFill}
// onMapReady={() => console.log(this.state.region)}
showsUserLocation={true}
region={region}
loadingEnabled={true}
// style={StyleSheet.absoluteFill}
textStyle={{ color: '#bc8b00' }}
containerStyle={{ backgroundColor: 'white', borderColor: '#BC8B00' }}
>
<Marker
coordinate={region}
title="Hello"
description="description"
pinColor="navy"
// onPress={() => alert("Provider Profile")}
// icon={require('../assets/camera-icon.png')}
onCalloutPress={() => alert("Provider Profile")}
/>
{this.state.providers.map((marker, index) => (<Marker key={index} coordinate={marker.coordinates} title={marker.username} />))}
{/* {this.state.nearest.map((marker, index) => (<Marker key={index} coordinate={marker.coordinates} title="f" />))} */}
</MapView>
{/* <Text>{this.state.region.latitude}</Text> */}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
padding: 30,
flex: 1,
alignItems: 'center'
},
map: {
position: 'absolute',
zIndex: -1,
top: 0,
left: 0,
right: 0,
bottom: 0,
},
});
export default Map;
Upvotes: 1
Views: 1508
Reputation: 598847
I think your database listener should look more like this:
const providerRef = firebase.database().ref('providers');
providerRef.on('value', snapshot => {
var newState = [];
console.log(snapshot.val());
snapshot.forEach((childSnapshot) => {
newState.push({
id: childSnapshot.val().id,
username: childSnapshot.val().username,
coordinates: {
longitude: childSnapshot.val().coordinates.longitude,
latitude: childSnapshot.val().coordinates.latitude,
}
});
});
this.setState({ providers: newState })
});
Changes from yours:
newState
inside the callback, so that you start out with an empty array each time you get data from Firebase.setState(...)
only after processing all data from the database, instead of after each item.Upvotes: 1