列出 geofire 区域内来自 firebase 的元素
List elements from firebase within geofire region
我正在尝试显示落在当前位置地理半径范围内的商家列表。我遇到的问题是数据源似乎没有填充任何行。
import React from 'react'
import { View, ListView, Image, Text, ActivityIndicator } from 'react-native'
import ParallaxScrollView from 'react-native-parallax-scroll-view'
import AlertMessage from '../Components/AlertMessage'
import Geocoder from 'react-native-geocoder'
import { Colors } from '../Themes/'
import { connect } from 'react-redux'
import MerchantRow from '../Components/MerchantRow'
import { firebaseApp } from '../Config/AppConfig'
const GeoFire = require('geofire')
// Styles
import styles from './Styles/MerchantListStyle'
class MerchantList extends React.Component {
watchID: ?number = null;
constructor (props) {
super(props)
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
}),
result: '',
city: 'you'
}
// Get references to several nodes we will need
rootRef = firebaseApp.database().ref();
merchantsRef = rootRef.child('merchants');
geofireRef = rootRef.child('locations');
this.geoFire = new GeoFire(geofireRef)
}
componentDidMount () {
navigator.geolocation.getCurrentPosition(
(position) => {
},
(error) => alert(JSON.stringify(error)),
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
)
this.watchID = navigator.geolocation.watchPosition((position) => {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
Geocoder.fallbackToGoogle('AIzaSyCPVaJK7Sx-Uv6X76508NUlrpF3YJBqgrk')
let ret = Geocoder.geocodePosition({lat, lng}).then((res)=>
{
city = res['0'].locality
this.setState({ city: city })
})
let radius = 40 // 40km
let currentLocation = [
position.coords.latitude,
position.coords.longitude
]
let geoQuery = this.geoFire.query({center: currentLocation, radius})
var merchants = [];
// For every key which matches our GeoQuery...
geoQuery.on('key_entered', function(key) {
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then(function(snapshot) {
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
this.setState({
loading: false,
dataSource: this.state.dataSource.cloneWithRows(merchants)
})
}).catch(function(error) {
console.log('Error fetching merchant data:', error)
})
})
})
}
componentWillUnmount () {
navigator.geolocation.clearWatch(this.watchID)
}
_renderRow (item) {
return (
<MerchantRow data={item} />
)
}
_noRowData () {
return this.state.dataSource.getRowCount() === 0
}
render () {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
enableEmptySections
pageSize={15}
renderScrollComponent={props => (
<ParallaxScrollView
backgroundColor={Colors.background}
contentBackgroundColor={Colors.background}
parallaxHeaderHeight={250}
renderBackground={() => (
<Image
style={styles.photo}
source={{uri: this.props.photo}}
defaultSource={require('../Images/Merchant_Header.png')}
/>
)}
renderForeground={() => (
<View key='parallax-header' style={styles.parallaxHeader}>
<Text style={styles.title}>
{'Choose a café near\n' + this.state.city + ' to start\n your order'}
</Text>
</View>
)}
/>
)}
/>
<AlertMessage title='Nothing to See Here, Move Along' show={this._noRowData()} />
</View>
)
}
}
const mapStateToProps = (state) => {
return {
// ...redux state to props here
}
}
const mapDispatchToProps = (dispatch) => {
return {
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MerchantList)
出现此问题是因为您使用的是普通回调函数,而不是使用使用粗箭头的 ES6 函数。
geoQuery.on('key_entered', function(key) {
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then(function(snapshot) {
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
this.setState({
loading: false,
dataSource: this.state.dataSource.cloneWithRows(merchants)
})
}).catch(function(error) {
console.log('Error fetching merchant data:', error)
})
})
this
对象应该引用 this.state.dataSource.cloneWithRows(merchants)
中的 class。但是,在 Javascript 中,正常回调 function() {}
将创建并绑定自己的 this
对象,而不是来自其父对象的对象,这意味着 this.state.dataSource.cloneWithRows(merchants)
现在无效。为防止这种情况,您应该使用不执行任何 this
绑定的 ES6 函数语法。
您更新后的代码应如下所示:
geoQuery.on('key_entered', (key) => { // Using fat arrows
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then((snapshot) => { // here too!
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
this.setState({
loading: false,
dataSource: this.state.dataSource.cloneWithRows(merchants)
})
}).catch((error) => { // If you are planning to use this here
console.log('Error fetching merchant data:', error)
})
})
如果你想使用普通的回调函数语法而不是ES6版本,你可以在函数外创建一个对此的引用,并在函数内使用新的引用。在这种情况下,您的代码应如下所示:
const that = this; // created a reference!
geoQuery.on('key_entered', function(key) {
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then(function(snapshot) {
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
that.setState({ // Use the reference here!
loading: false,
dataSource: that.state.dataSource.cloneWithRows(merchants) // Here too!
})
}).catch(function(error) {
console.log('Error fetching merchant data:', error)
})
})
我正在尝试显示落在当前位置地理半径范围内的商家列表。我遇到的问题是数据源似乎没有填充任何行。
import React from 'react'
import { View, ListView, Image, Text, ActivityIndicator } from 'react-native'
import ParallaxScrollView from 'react-native-parallax-scroll-view'
import AlertMessage from '../Components/AlertMessage'
import Geocoder from 'react-native-geocoder'
import { Colors } from '../Themes/'
import { connect } from 'react-redux'
import MerchantRow from '../Components/MerchantRow'
import { firebaseApp } from '../Config/AppConfig'
const GeoFire = require('geofire')
// Styles
import styles from './Styles/MerchantListStyle'
class MerchantList extends React.Component {
watchID: ?number = null;
constructor (props) {
super(props)
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
}),
result: '',
city: 'you'
}
// Get references to several nodes we will need
rootRef = firebaseApp.database().ref();
merchantsRef = rootRef.child('merchants');
geofireRef = rootRef.child('locations');
this.geoFire = new GeoFire(geofireRef)
}
componentDidMount () {
navigator.geolocation.getCurrentPosition(
(position) => {
},
(error) => alert(JSON.stringify(error)),
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
)
this.watchID = navigator.geolocation.watchPosition((position) => {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
Geocoder.fallbackToGoogle('AIzaSyCPVaJK7Sx-Uv6X76508NUlrpF3YJBqgrk')
let ret = Geocoder.geocodePosition({lat, lng}).then((res)=>
{
city = res['0'].locality
this.setState({ city: city })
})
let radius = 40 // 40km
let currentLocation = [
position.coords.latitude,
position.coords.longitude
]
let geoQuery = this.geoFire.query({center: currentLocation, radius})
var merchants = [];
// For every key which matches our GeoQuery...
geoQuery.on('key_entered', function(key) {
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then(function(snapshot) {
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
this.setState({
loading: false,
dataSource: this.state.dataSource.cloneWithRows(merchants)
})
}).catch(function(error) {
console.log('Error fetching merchant data:', error)
})
})
})
}
componentWillUnmount () {
navigator.geolocation.clearWatch(this.watchID)
}
_renderRow (item) {
return (
<MerchantRow data={item} />
)
}
_noRowData () {
return this.state.dataSource.getRowCount() === 0
}
render () {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
enableEmptySections
pageSize={15}
renderScrollComponent={props => (
<ParallaxScrollView
backgroundColor={Colors.background}
contentBackgroundColor={Colors.background}
parallaxHeaderHeight={250}
renderBackground={() => (
<Image
style={styles.photo}
source={{uri: this.props.photo}}
defaultSource={require('../Images/Merchant_Header.png')}
/>
)}
renderForeground={() => (
<View key='parallax-header' style={styles.parallaxHeader}>
<Text style={styles.title}>
{'Choose a café near\n' + this.state.city + ' to start\n your order'}
</Text>
</View>
)}
/>
)}
/>
<AlertMessage title='Nothing to See Here, Move Along' show={this._noRowData()} />
</View>
)
}
}
const mapStateToProps = (state) => {
return {
// ...redux state to props here
}
}
const mapDispatchToProps = (dispatch) => {
return {
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MerchantList)
出现此问题是因为您使用的是普通回调函数,而不是使用使用粗箭头的 ES6 函数。
geoQuery.on('key_entered', function(key) {
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then(function(snapshot) {
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
this.setState({
loading: false,
dataSource: this.state.dataSource.cloneWithRows(merchants)
})
}).catch(function(error) {
console.log('Error fetching merchant data:', error)
})
})
this
对象应该引用 this.state.dataSource.cloneWithRows(merchants)
中的 class。但是,在 Javascript 中,正常回调 function() {}
将创建并绑定自己的 this
对象,而不是来自其父对象的对象,这意味着 this.state.dataSource.cloneWithRows(merchants)
现在无效。为防止这种情况,您应该使用不执行任何 this
绑定的 ES6 函数语法。
您更新后的代码应如下所示:
geoQuery.on('key_entered', (key) => { // Using fat arrows
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then((snapshot) => { // here too!
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
this.setState({
loading: false,
dataSource: this.state.dataSource.cloneWithRows(merchants)
})
}).catch((error) => { // If you are planning to use this here
console.log('Error fetching merchant data:', error)
})
})
如果你想使用普通的回调函数语法而不是ES6版本,你可以在函数外创建一个对此的引用,并在函数内使用新的引用。在这种情况下,您的代码应如下所示:
const that = this; // created a reference!
geoQuery.on('key_entered', function(key) {
// ... look up the merchant data for that key ...
// console.log(key)
merchantsRef.child(key).once('value').then(function(snapshot) {
// ... and add it to the matches array
merchants.push(snapshot.val())
console.log(merchants)
that.setState({ // Use the reference here!
loading: false,
dataSource: that.state.dataSource.cloneWithRows(merchants) // Here too!
})
}).catch(function(error) {
console.log('Error fetching merchant data:', error)
})
})