如何在 React-native 组件之间导航?
How to navigate between React-native Component?
当我点击 <TouchableOpacity onPress= this.onPressCheckParkingStatus.bind(this)}>
显示错误 Navigator: 无法读取未定义的 属性 'push'
尽管它在 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.
我的导航器正在从登录到楼层工作。我正在加载 FloorItem 作为 Floor class 中的组件,这是我的问题:-
**Navigator: Cannot read property 'push' of undefined**
我没有得到基于组件的导航器示例,这就是我在这里提出问题的原因。
提前致谢。我受够了 now.I 不知道为什么它在一个组件上工作而不在其他组件上工作。
您的代码在这里看起来不错。但唯一的问题是您在组件数组中传递 {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% 测试并且可以正常工作。
当我点击 <TouchableOpacity onPress= this.onPressCheckParkingStatus.bind(this)}>
显示错误 Navigator: 无法读取未定义的 属性 'push'
尽管它在 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.
我的导航器正在从登录到楼层工作。我正在加载 FloorItem 作为 Floor class 中的组件,这是我的问题:-
**Navigator: Cannot read property 'push' of undefined**
我没有得到基于组件的导航器示例,这就是我在这里提出问题的原因。 提前致谢。我受够了 now.I 不知道为什么它在一个组件上工作而不在其他组件上工作。
您的代码在这里看起来不错。但唯一的问题是您在组件数组中传递 {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% 测试并且可以正常工作。