2016-03-04 54 views
0

使用React-Native並嘗試學習ES6語法。我昨天有類似的問題,並得到了解決方案。我加如何使用ES6與原生

.bind(本)

我的我的函數調用,問題就解決了。我用另一個函數調用再次遇到了同樣的問題,我無法追查發生了什麼。錯誤消息是相同的。

未定義不是(評價 'this.props.drawer.open')一個對象

的功能是:

onClickMenu() { 
    this.props.drawer.open(); 
    } 

並且它被稱爲與該:

onPress={this.onClickMenu.bind(this)} 

這是整個代碼。如果你看到的東西不是這個問題,看起來不對,請讓我知道! *注意我已將「var」替換爲「let」。從我讀過的內容來看,正確的ES6語法可以在任何地方使用它?

'use strict'; 

const React = require('react-native'); 
const { 
    Text, 
    View, 
    Component, 
    StyleSheet, 
    SwitchAndroid 
} = React; 

import { Button } from 'react-native-material-design'; 
import Store from 'react-native-simple-store'; 
import Underscore from 'underscore'; 
import RNGMap from 'react-native-gmaps'; 
import Polyline from 'react-native-gmaps/Polyline'; 
import Icon from 'react-native-vector-icons/Ionicons'; 
import SettingsService from './../settings/settings.service'; 
//import subdivisions from './subdivisions.json'; 
import commonStyles from './../common/styles'; 

let accessToken = null; 
let userId = null; 
let routeId = null; 
let subdivisionId = null; 

SettingsService.init('Android'); 

class Map extends Component { 
    constructor(props) { 
    super(props) 
    this.state = { 
     odometer: 0, 
     mapWidth: 300, 
     mapHeight: 300, 
     enabled: false, 
     isMoving: false, 
     currentLocation: undefined, 
     locationManager: undefined, 
     paceButtonIcon: 'Start Trip', 
     navigateButtonIcon: 'navigate', 
     paceButtonStyle: commonStyles.disabledButton, 
     // mapbox 
     center: { 
     lat: 40.7223, 
     lng: -73.9878 
     }, 
     zoom: 10, 
     markers: [] 
    } 
    } 

    componentDidMount() { 
    Store.get('token').then((token) => { 
     accessToken = token.access_token; 
     userId = token.userId; 
    }); 
    let me = this, 
     gmap = this.refs.gmap; 

    this.locationManager = this.props.locationManager; 

    // location event 
    this.locationManager.on("location", function(location) { 
     console.log('- location: ', JSON.stringify(location)); 
     me.setCenter(location); 
     gmap.addMarker(me._createMarker(location)); 

     me.setState({ 
     odometer: (location.odometer/1000).toFixed(1) 
     }); 

     // Add a point to our tracking polyline 
     if (me.polyline) { 
     me.polyline.addPoint(location.coords.latitude, location.coords.longitude); 
     } 
    }); 
    // http event 
    this.locationManager.on("http", function(response) {}); 
    // geofence event 
    this.locationManager.on("geofence", function(geofence) {}); 
    // error event 
    this.locationManager.on("error", function(error) { 
     console.log('- ERROR: ', JSON.stringify(error)); 
    }); 
    // motionchange event 
    this.locationManager.on("motionchange", function(event) { 
     me.updatePaceButtonStyle(); 
    }); 

    // getGeofences 
    this.locationManager.getGeofences(function(rs) { 
    }, function(error) { 
     console.log("- getGeofences ERROR", error); 
    }); 

    SettingsService.getValues(function(values) { 
     values.license = "eddbe81bbd86fa030ea466198e778ac78229454c31100295dae4bfc5c4d0f7e2"; 
     values.orderId = 1; 
     values.stopTimeout = 0; 
     //values.url = 'http://192.168.11.120:8080/locations'; 

     me.locationManager.configure(values, function(state) { 
     me.setState({ 
      enabled: state.enabled 
     }); 
     if (state.enabled) { 
      me.initializePolyline(); 
      me.updatePaceButtonStyle() 
     } 
     }); 
    }); 

    this.setState({ 
     enabled: false, 
     isMoving: false 
    }); 
    } 
    _createMarker(location) { 
    return { 
     title: location.timestamp, 
     id: location.uuid, 
     icon: require("image!transparent_circle"), 
     anchor: [0.5, 0.5], 
     coordinates: { 
     lat: location.coords.latitude, 
     lng: location.coords.longitude 
     } 
    }; 
    } 

    initializePolyline() { 
    // Create our tracking Polyline 
    let me = this; 
    Polyline.create({ 
     width: 12, 
     points: [], 
     geodesic: true, 
     color: '#2677FF' 
    }, function(polyline) { 
     me.polyline = polyline; 
    }); 
    } 

    onClickMenu() { 
    this.props.drawer.open(); 
    } 

    onClickEnable() { 
    let me = this; 
    if (!this.state.enabled) { 
     this.locationManager.start(function() { 
     me.initializePolyline(); 
     }); 
    } else { 
     this.locationManager.resetOdometer(); 
     this.locationManager.stop(); 
     this.setState({ 
     markers: [{}], 
     odometer: 0 
     }); 
     this.setState({ 
     markers: [] 
     }); 
     if (this.polyline) { 
     this.polyline.remove(function(result) { 
      me.polyline = undefined; 
     }); 
     } 
    } 

    this.setState({ 
     enabled: !this.state.enabled 
    }); 
    this.updatePaceButtonStyle(); 
    } 

    onClickPace() { 
    if (!this.state.enabled) { 
     return; 
    } 
    let isMoving = !this.state.isMoving; 
    this.locationManager.changePace(isMoving); 

    this.setState({ 
     isMoving: isMoving 
    }); 
    this.updatePaceButtonStyle(); 
    } 

    onClickLocate() { 
    let me = this; 

    this.locationManager.getCurrentPosition({ 
     timeout: 30 
    }, function(location) { 
     me.setCenter(location); 
    }, function(error) { 
     console.error('ERROR: getCurrentPosition', error); 
     me.setState({ 
     navigateButtonIcon: 'navigate' 
     }); 
    }); 
    } 

    onRegionChange() {} 

    setCenter(location) { 
    this.setState({ 
     navigateButtonIcon: 'navigate', 
     center: { 
     lat: location.coords.latitude, 
     lng: location.coords.longitude 
     }, 
     zoom: 16 
    }); 
    } 

    onLayout() { 
    let me = this, 
     gmap = this.refs.gmap; 

    this.refs.workspace.measure(function(ox, oy, width, height, px, py) { 
     me.setState({ 
     mapHeight: height, 
     mapWidth: width 
     }); 
    }); 
    } 

    updatePaceButtonStyle() { 
    let style = commonStyles.disabledButton; 
    if (this.state.enabled) { 
     style = (this.state.isMoving) ? commonStyles.redButton : commonStyles.greenButton; 
    } 
    this.setState({ 
     paceButtonStyle: style, 
     paceButtonIcon: (this.state.enabled && this.state.isMoving) ? 'Stop Trip' : 'Start Trip' 
    }); 
    } 

    render() { 
    return (
     <View style={commonStyles.container}> 
     <View style={commonStyles.topToolbar}> 
      <Icon.Button name="android-options" onPress={this.onClickMenu.bind(this)} backgroundColor="transparent" size={30} color="#000" style={styles.btnMenu} underlayColor={"transparent"} /> 
      <Text style={commonStyles.toolbarTitle}>Background Geolocation</Text> 
      <SwitchAndroid onValueChange={this.onClickEnable.bind(this)} value={this.state.enabled} /> 
     </View> 
     <View ref="workspace" style={styles.workspace} onLayout={this.onLayout.bind(this)}> 

      <RNGMap 
      ref={'gmap'} 
      style={{width: this.state.mapWidth, height: this.state.mapHeight}} 
      markers={this.state.markers} 
      zoomLevel={this.state.zoom} 
      onMapChange={(e) => console.log(e)} 
      onMapError={(e) => console.log('Map error --> ', e)} 
      center={this.state.center} /> 

     </View> 
     <View style={commonStyles.bottomToolbar}> 
      <Icon.Button name={this.state.navigateButtonIcon} onPress={this.onClickLocate.bind(this)} size={25} color="#000" underlayColor="#ccc" backgroundColor="transparent" style={styles.btnNavigate} /> 
      <Text style={{fontWeight: 'bold', fontSize: 18, flex: 1, textAlign: 'center'}}>{this.state.odometer} km</Text> 
      <Button raised={true} 
        text={this.state.paceButtonIcon} 
        onPress={this.onClickPace.bind(this)} 
        overrides={{backgroundColor:"#e12429",textColor:"#ffffff"}} 
        style={this.state.paceButtonStyle}></Button> 
      <Text>&nbsp;</Text> 
     </View> 
     </View> 
    ); 
    } 
}; 

const styles = StyleSheet.create({ 
    workspace: { 
    flex: 1 
    } 
}); 

module.exports = Map; 

UPDATE: 經由終端ADB調試示出了同樣的錯誤 console

因此,這裏是代碼其餘部分。排除故障。我將這些項目文件添加到了一個plunker。這是一個我正在使用的演示項目。 plunker

'use strict'; 

const React = require('react-native'); 
const { 
    Text, 
    Component, 
    StyleSheet, 
    AppRegistry 
} = React; 

import Map from './map/map'; 
import Drawer from 'react-native-drawer'; 
import Settings from './settings/settings.android'; 
import Icon from 'react-native-vector-icons/Ionicons'; 
import BackgroundGeolocation from 'react-native-background-geolocation-android'; 

global.bgGeo = BackgroundGeolocation; 

class App extends Component { 
    onClickMenu() { 
    this.props.refs.drawer.open(); 
    } 

    render() { 
    return (
     <Drawer ref="drawer" side="right" acceptPan={false} content={<Settings drawer={this.refs.drawer} locationManager={BackgroundGeolocation} />}> 
     <Map drawer={this.refs.drawer} locationManager={BackgroundGeolocation} />  
     </Drawer> 
    ); 
    } 
}; 

module.exports = App; 

UPDATE: screenshot

+0

我不認爲你的代碼顯示哪些'道具'傳遞給你的組件,錯誤並沒有指定哪一部分是未定義的。你假設context沒有被傳遞,是否有可能'抽屜'(甚至'props')沒有被定義?有些日誌會證實它。 –

+0

好的,我如何獲得日誌? – texas697

+0

只需console.log,XCode將在運行應用程序時通過調試面板顯示JS日誌記錄。 [更多信息](http://stackoverflow.com/questions/30115372/how-to-do-logging-in-react-native) –

回答

1

我不認爲你可以通過參傳遞給部件以這樣的方式, 肯定它不會在React工作,我不認爲它會在這樣一個工作 方式也在React-Native之內。

我不清楚爲什麼你從 Map組件試圖.openDrawer,因爲它看起來像Map部件僅能夠 訪問時,Drawer是開放的,但是,如果你想訪問父 行爲從孩子的一個好的模式是通過功能 爲孩子執行(你可以爭辯說,這實際上是不好的 和傳遞事件是一個更強大的模式)。

我從來沒有使用的圖書館,所以我不上它的使用完全清楚,但 你可以通過傳遞函數是這樣的:

class Application extends Component { 

    closeControlPanel =() => { 
    this.refs.drawer.close() 
    }; 
    openControlPanel =() => { 
    this.refs.drawer.open() 
    }; 
    render() { 
    return (
     <Drawer 
     ref="drawer" 
     content={<ControlPanel />} 
     > 
     <Map onMenuClose={ this.closeControlPanel.bind(this) } /> 
     </Drawer> 
    ) 
    } 
}) 

在這種情況下this.props.onMenuClose應附加到一個動作,這,執行時會觸發父功能並執行this.refs.drawer.close功能。

+0

好的。我現在不在電腦上,但會盡快插上電源。這實際上是我的第一個反應原生項目,所以我正在學習。我把它作爲一個演示項目,我想我會將它轉換爲ES6,以便與大多數項目保持一致。使用演示項目學習的問題是你永遠不知道什麼是笨蛋製作的 – texas697