Listview 列出geofire区域内firebase中的元素

Listview 列出geofire区域内firebase中的元素,listview,firebase,react-native,geofire,Listview,Firebase,React Native,Geofire,我试图显示一个在当前位置地理半径范围内的商户列表。我遇到的问题是,数据源似乎没有填充任何行 import React from 'react' import { View, ListView, Image, Text, ActivityIndicator } from 'react-native' import ParallaxScrollView from 'react-native-parallax-scroll-view' import AlertMessage from '../Comp

我试图显示一个在当前位置地理半径范围内的商户列表。我遇到的问题是,数据源似乎没有填充任何行

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)
从“React”导入React
从“react native”导入{View、ListView、图像、文本、ActivityIndicator}
从“反应本机视差滚动视图”导入视差滚动视图
从“../Components/AlertMessage”导入AlertMessage
从“react native Geocoder”导入地理编码器
从“../Themes/”导入{Colors}
从“react redux”导入{connect}
从“../Components/MerchantRow”导入MerchantRow
从“../Config/AppConfig”导入{firebaseApp}
const GeoFire=require('GeoFire')
//风格
从“./styles/MerchantListStyle”导入样式
类MerchantList扩展了React.Component{
watchID:?number=null;
建造师(道具){
超级(道具)
此.state={
数据源:新建ListView.dataSource({
行已更改:(行1,行2)=>行1!==行2
}),
结果:“”,
城市:你
}
//获取我们需要的几个节点的引用
rootRef=firebaseApp.database().ref();
merchantsRef=rootRef.child('merchants');
geofireRef=rootRef.child('locations');
this.geoFire=新的geoFire(geofireRef)
}
组件安装(){
navigator.geolocation.getCurrentPosition(
(职位)=>{
},
(错误)=>警报(JSON.stringify(错误)),
{enableHighAccurance:true,超时:20000,最大值:1000}
)
this.watchID=navigator.geolocation.watchPosition((位置)=>{
var lat=位置坐标纬度;
var lng=位置坐标经度;
地理编码器。回退到日志('AIzaSyCPVaJK7Sx-Uv6X76508NUlrpF3YJBqgrk')
让ret=Geocoder.geocodePosition({lat,lng})。然后((res)=>
{
城市=res['0']。地点
this.setState({city:city})
})
让半径=40//40km
让currentLocation=[
位置坐标纬度,
位置坐标经度
]
让geoQuery=this.geoFire.query({center:currentLocation,radius})
var=[];
//对于与我们的地理查询匹配的每个键。。。
geoQuery.on('key_entered',函数(key){
//…查找该密钥的商户数据。。。
//console.log(键)
merchantsRef.child(键)。一次('value')。然后(函数(快照){
//…并将其添加到matches数组中
bunchers.push(snapshot.val())
控制台日志(商户)
这是我的国家({
加载:false,
dataSource:this.state.dataSource.cloneWithRows(商户)
})
}).catch(函数(错误){
console.log('获取商户数据时出错:',错误)
})
})
})
}
组件将卸载(){
navigator.geolocation.clearWatch(this.watchID)
}
_渲染箭头(项目){
返回(
)
}
_noRowData(){
返回此.state.dataSource.getRowCount()==0
}
渲染(){
返回(
(
(
)}
renderForeground={()=>(
{'Choose a cafénear\n'+this.state.city+'开始\n您的订单'}
)}
/>
)}
/>
)
}
}
常量mapStateToProps=(状态)=>{
返回{
//…将状态重新复制到这里的道具
}
}
const mapDispatchToProps=(调度)=>{
返回{
}
}
导出默认连接(MapStateTrops、mapDispatchToProps)(商品列表)

出现问题的原因是您使用的是普通回调函数,而不是使用使用fat箭头的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(招商局)
中的类。但是,在Javascript中,普通回调函数({}将创建并绑定自己的
这个
对象,而不是来自其父对象的
对象,这意味着
this.state.dataSource.cloneWithRows(merchants)
现在无效。为了防止这种情况,您应该使用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)
    })
  })
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)
        })
      })
如果要使用普通回调函数语法而不是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)
    })
  })
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)
        })
      })