0

當我點擊<TouchableOpacity onPress= this.onPressCheckParkingStatus.bind(this)}>如何在React-native組件之間導航?

它顯示錯誤導航:雖然它在Login.js to Floor.js工作無法讀取的不確定 財產「推」。但它不在FloorItem.js中工作。

這裏是我的器件結構: -

src  //folder 
components //folder 
    floor //folder 
     Floor.js 
     FloorItem.js 
    login 
     .Login.js 
     .LoginFooter.js 
    parking 
     parking.js 
index.js 
index.ios.js 

也有JS很多的,但上面提到的需要。

Login.js

import React, { Component } from 'react'; 
import { 
    StyleSheet,View,Text,Image,TextInput,TouchableOpacity, 
    KeyboardAvoidingView,ActivityIndicatorIOS,AsyncStorage 
    } from 'react-native'; 

import LoginForm from './LoginForm'; 
import LoginFooter from './LoginFooter'; 

const ACCESS_TOKEN = 'access_token'; 

export default class Login extends Component { 
    constructor(){ 
     super(); 
     this.state = { 
     username: "", 
     password: "", 
     error: "", 
     accessToken:"", 
     showProgress:false 
    } 
} 

storeToken(access_token){ 
    try { 
     console.log("token for setting= "+access_token); 
     AsyncStorage.setItem(ACCESS_TOKEN,access_token); 

    } catch (error) { 
     console.log("error in logging token="); 
     console.log(error.name); 
     console.log(error.message); 
     console.log(error.stack); 
     this.redirect('login'); 
    } 
}  
redirect(routeName) {  
     this.props.navigator.push({ 
      name: routeName 
     }); 
}  
onPressSignin() { 
     try { 
      console.log('login from window'); 
      this.setState({showProgress: true}); 
      this.error="";    
      **this.redirect('floor');** 

     } catch (error) { 
      console.log("error in logging token="); 
      console.log(error.name); 
      console.log(error.message); 
      console.log(error.stack); 
     } 
    } 

render() { 
    return (
     <View style={styles.container}> 

     <View style={styles.logoContainer}> 
      <Image 
      style={styles.logo} 
      source={require('../../images/logo.png')}/> 
      <Text 
      style={styles.logoTitle}>Smart Parking...</Text> 
     </View> 
     <View> 
     <Text style={Loginformstyles.error}> 
      {this.state.error} 
      </Text> 
     </View> 

     <KeyboardAvoidingView behavior='padding' style={styles.formContainer}> 

      <View style={Loginformstyles.container}> 
      <TextInput 
       onChangeText={ (text)=> this.setState({ username : text }) } 
       placeholder ="Username" 
       placeholderTextColor="rgba(0,0,0,0.6)" 
       style={Loginformstyles.input} 
       returnKeyType="next" 
       keyboardType="email-address" 
       autoCapitalize="none" 
       autoCorrect={false} 
       onSubmitEditing={() => this.passwordInput.focus()} 
      /> 
      <TextInput 
       placeholder="Password" 
       placeholderTextColor="rgba(0,0,0,0.6)" 
       secureTextEntry={true} 
       style={Loginformstyles.input} 
       returnKeyType="go" 
       onChangeText={(text)=>this.setState({password:text})} 
      /> 

      <TouchableOpacity onPress={this.onPressSignin.bind(this)} 
       style={Loginformstyles.buttonContainer}> 
       <Text style={Loginformstyles.buttonText}>Sign in</Text> 
      </TouchableOpacity> 
      <TouchableOpacity> 
       <Text style={Loginformstyles.forgotPassword}>Forgot Password</Text> 
      </TouchableOpacity> 

      </View> 
     </KeyboardAvoidingView> 

     <View style={styles.footerContainer}> 
      <LoginFooter/> 
     </View> 
     </View> 
    ); 
    } 
} 

這裏我不提,因爲CSS文件是越來越笨重。登錄時單擊它將重定向到所需的樓層組件。 在地板組件中,我繼承了FloorItem

**Floor.js** 

import React, { Component } from 'react'; 
import { 
    StyleSheet, 
    View, 
    Text, 
    Image,AsyncStorage, 
    KeyboardAvoidingView 
} from 'react-native'; 
import FloorItem from './FloorItem'; 
const ACCESS_TOKEN = 'access_token'; 
export default class Floor extends Component { 
    constructor(props){ 
    super(props); 
    //this.redirect.bind(this,'floor'); 
    this.state={ 
     parking_details:[], 
     accessToken:"" 
    } 
    } 
async getToken() { 
    try { 
     let accessToken = await AsyncStorage.getItem(ACCESS_TOKEN); 
     console.log(accessToken); 
     if(!accessToken) { 
      this.redirect('login'); 
     } else { 
      this.setState({accessToken: accessToken}) 
      //this.fetchFloorDetails(); 
     } 
    } catch(error) { 
     console.log(error.name); 
     console.log(error.message); 
     console.log(error.stack); 
     this.redirect('login'); 
    } 
    } 
componentWillMount() { 
    this.fetchFloorDetails(); 
    } 
redirect(routeName) { 
    this.props.navigator.push({ 
    name: routeName 
    }); 
} 
fetchFloorDetails(){ 
     try { 
      this.getToken(); 
      var parkingInfo=[ 
      { available_count:0,floor_no:5 ,totalparkingspace:150}, 
      { available_count:0,floor_no:4 ,totalparkingspace:140}, 
      { available_count:0,floor_no:3 ,totalparkingspace:180}, 
      { available_count:52,floor_no:2 ,totalparkingspace:120}, 
      { available_count:24,floor_no:1 ,totalparkingspace:80}, 
      { available_count:0,floor_no:0 ,totalparkingspace:170} 
      ]; 
      this.setState({parking_details:parkingInfo}); 
     } catch (error) { 
     console.log(error.name); 
     console.log(error.message); 
     console.log(error.stack); 
     } finally { 
     } 
} 
    render(){ 
     { 
     var parkingFloors=[]; 
      this.state.parking_details.map(function(item){ 
      parkingFloors.push(
       <FloorItem navigator={this.props.navigator} 
      key={item.floor_no} 
      parkingAvailablecount={item.available_count} 
      parkingFloorCount={item.floor_no} 
      totalParkingSpace={item.totalparkingspace} /> 
      ); 
      }) 
     } 
    return (
     <View style={styles.container}> 
     <View style={styles.bgImageWrapper}> 
      <Image source={require('../../images/bg.png')} style={styles.bgImage} /> 
      </View> 
     <View style={styles.locationContainer}> 
      <Image 
      style={styles.location} 
      source={require('../../images/location.png')}/> 
      <Text 
      style={styles.locationTitle}>12920 38th Ave S.E. Bellevue, Wa 98006</Text> 
     </View> 
     <View style={styles.floorItemContainer}> 
      {parkingFloors} 
     </View> 
     </View> 
    ); 
    } 
} 

**FloorItem.js** 

    import React, { Component } from 'react'; 
import { 
    StyleSheet, 
    View, 
    Text, 
    Image, 
    TouchableOpacity 
} from 'react-native'; 
import renderIf from '../renderIf'; 

const ACCESS_TOKEN = 'access_token'; 

export default class FloorItem extends Component { 

    constructor(props){ 
    super(props); 
    this.state = { 
     isParkingAvailable: false, 
     accessToken: "" 
     }; 
    this.set_object=this.set_object.bind(this); 
    this.props.totalParkingSpace=0; 
    this.set_parking_floorImages=this.set_parking_floorImages.bind(this); 
    //this.redirect=this.redirect.bind(this); 
    // Toggle the state every second 
/* setInterval(() => { 
     this.setState({ isParkingAvailable: !this.state.isParkingAvailable }); 
    }, 1000); 
*/ 
    } 

redirect(routeName){ 
this.props.navigator.push({ 
    name: routeName 
}); 
} 

async getToken() { 
    try { 
    let accessToken = await AsyncStorage.getItem(ACCESS_TOKEN); 
     console.log(accessToken); 
    if(!accessToken) { 
     this.redirect('login'); 
    } else { 
     this.setState({accessToken: accessToken}) 
    } 
    } catch(error) { 
     console.log("Something went wrong"); 
     this.redirect('login'); 
    } 
} 
onPressCheckParkingStatus=()=>{ 
    this.getToken();  
    this.redirect('parking'); 
} 

    render() { 
    this.set_object(); 
    let parkingFloorImage = this.state.isParkingAvailable ? require('../../images/floor.png') : require('../../images/floor_full.png'); 
    let parkingFloorNumberImage =this.set_parking_floorImages(this.props.parkingFloorCount); 
    //this.state.isParkingAvailable ? require('../../images/f00.png') : require('../../images/f01.png'); 
    return (
     <View style={styles.container}> 
     <View style={styles.textContainer}> 
      {renderIf(this.state.isParkingAvailable)(
      <TouchableOpacity onPress={this.onPressCheckParkingStatus.bind(this)}> 
       <View style={styles.parkingAvailableTextContainer}> 
       <Text 
       style={styles.parkingAvailableText}>AVAILABLE</Text> 
       <Text 
       style={styles.parkingNumberText}> 
        {this.props.parkingAvailablecount}</Text> 

       </View> 
      </TouchableOpacity> 
     )} 
      {renderIf(!this.state.isParkingAvailable)(
      <View style={styles.parkingFullTextContainer}> 
       <Text 
       style={styles.parkingFullText}>PARKING FULL</Text> 
      </View> 
     )} 
     </View> 
     <View style={styles.floorImageContainer}> 
      <Image 
      style={styles.floorImage} 
      source={parkingFloorImage}/> 
      <Image 
      style={styles.floorNumberImage} 
      source={parkingFloorNumberImage}/> 
     </View> 
     </View> 
    ); 
    } 
} 


**index.js** 

/** 
* Sample React Native App 
* https://github.com/facebook/react-native 
* @flow 
*/ 

import React, { Component} from 'react'; 
import { Text, Navigator, TouchableHighlight } from 'react-native'; 
import SplashScreen from 'react-native-splash-screen'; 
import { AppRegistry } from 'react-native'; 
import Login from './src/components/login/Login'; 
import Floor from './src/components/floor/Floor'; 
import FloorItem from './src/components/floor/FloorItem'; 
import Parking from './src/components/parking/Parking'; 



export default class SmartParking extends Component { 

    componentDidMount() { 
     SplashScreen.hide(); 
    } 
    constructor(){ 
    super() 
    } 

    renderScene(route, navigator) { 


    if(route.name == 'login') { 
     return <Login navigator={navigator} /> 
    } 
    if(route.name == 'floor') { 
      return <Floor navigator={navigator} {...route.props} /> 
    } 
    if(route.name == 'parking') { 
      return <Parking navigator={navigator} {...route.props} /> 
    } 

    } 

render(){ 
    return(

     <Navigator initialRoute={ { name : 'login' } } 
      renderScene={this.renderScene.bind(this)} 
      /> 
    ); 
} 
} 

AppRegistry.registerComponent('SmartParking',() => SmartParking); 


index.io.js //Main file 

import { 
    AppRegistry, 
} from 'react-native'; 

import index from './index.js' 

AppRegistry.registerComponent('examples',() => index); 

Application Flow:--- 
index.io.js ==>index.js==>login.js==>floor.js(FoorItem.js). here FloorItem.js has been accessing by component in floor.js. 

我的導航器正在登錄到樓層工作。我加載FloorItem在地板類成分,這是我的問題: -

 **Navigator: Cannot read property 'push' of undefined** 

我沒有基於組件的導航例子,這就是爲什麼我在這裏提出我的問題。 在此先感謝。我現在厭倦了。我不知道爲什麼它在一個組件上工作,而不是在其他組件上工作。

回答

0

你的代碼在這裏看起來不錯。但唯一的問題是你在組件數組中傳遞{this.props.navigator}。只有這是問題。

因此,在Floor.js中更改您的代碼。

var parkingFloors=[],navigate={}; 
    navigate=this.props.navigator; 
     this.state.parking_details.map(function(item){ 
     parkingFloors.push(
      <FloorItem navigator=navigate 
     key={item.floor_no} 
     parkingAvailablecount={item.available_count} 
     parkingFloorCount={item.floor_no} 
     totalParkingSpace={item.totalparkingspace} /> 
     ); 
     }) 

它的100%測試和它的工作。

+0

謝謝你,我明白了。昨天我整天都不耐煩。它現在正在工作。 – ram

+0

感謝您的讚賞。 –