如何在React-native组件之间导航?

时间:2017-04-12 08:53:29

标签: javascript react-native react-native-ios react-navigation

点击<TouchableOpacity onPress= this.onPressCheckParkingStatus.bind(this)}>

显示错误导航器:无法读取属性&#39;推送&#39;未定义 虽然它在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因为文件变得笨重。在登录时单击它将重定向到所需的楼层组件。            在floor组件中,我继承了 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.

我的导航器正在从登录到楼层工作。我在Floor类中加载FloorItem作为组件,这是我的问题: -

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

我没有得到基于组件的导航器示例,这就是我在这里提出问题的原因。 提前致谢。我现在厌烦了。我不知道为什么它在一个组件上工作而不是在其他组件上工作。

1 个答案:

答案 0 :(得分: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%经过测试,它正在运行。