2017-06-25 33 views
0

我试图显示属于当前位置的地理半径内的商户列表。我遇到的问题是数据源似乎没有被任何行填充。从地理位置区域内的Firebase列出元素

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) 

回答

1

发生此问题的原因是您使用的是普通的回调函数,而不是使用使用胖箭头的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)。但是,在Javascript正常回调function() {}将创建并绑定它自己的this对象而不是其父对象,这意味着this.state.dataSource.cloneWithRows(merchants)现在是无效的。为了防止出现这种情况,您应该使用ES6函数语法,它没有任何this绑定。

你更新的代码应该是这样的:

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) 
     }) 
     })