问题
I have attempted to combine the usage of React Native Navbar & React Native Router Flux to simplify the make of my RN app. In doing so, I have gotten to a point at which I am switching routes via React Native Router Flux until after I get to the home page, in which I need to use Navigator again.
The reason being is that I don't think it is yet possible to create something like this with React Native Router Flux. What I am trying to do is create a simple transition from the login/signup page to the home feed pages that are navigated in between with a side menu. Of course, you don't want to create a different side menu on every single component, so I mimicked what's done in the React Native Starter App Repo for a start. But when I attempt to transition from the login screen to the home screen (which is essentially the React Native Starter App code) I get the following error:
My Home Page code is the following (again pretty much taken from React Native Starter App):
//user home feed with personalized news based
//on onboarding experience
'use strict';
//component variables
var React = require('react-native');
var { Component, StyleSheet, Navigator, Text, View } = React;
var EventEmitter = require('EventEmitter');
var Subscribable = require('Subscribable');
//libraries
var NavigationBar = require('react-native-navbar');
var SideMenu = require('react-native-side-menu');
// App Globals
var AppStyles = require('../styles/styles');
// Components
var Icons = require('../components/icons');
var Menu = require('../components/menu');
// Screens / Pages
var Index = require('../screens/soon');
/* ==============================
Main Navigator with Sidemenu
=============================== */
module.exports = React.createClass({
mixins: [Subscribable.Mixin],
//before application load
getInitialState: function() {
return {
touchToClose: true,
disableGestures: false,
};
},
//on application load
componentWillMount: function() {
this.eventEmitter = new EventEmitter();
},
//When Back Button from NavBar is Clicked
onLeftBackButtonPress: function(navigator) {
this.refs.rootNavigator.pop();
},
//When Hamburger from NavBar is Clicked
onLeftButtonPress: function() {
this.eventEmitter.emit('toggleMenu');
},
//Navigates to page from menu
navigate: function(title, link) {
this.refs.rootSidebarMenu.closeMenu();
this.refs.rootNavigator.replace({
title: title,
component: link,
});
},
//Generate Custom Navbar
renderScene: function(route, navigator) {
var Component = route.component;
var navBar = route.navigationBar;
// Icons
var MenuIcon = Icons.MenuIcon;
var BackIcon = Icons.BackIcon;
// Navbar Setup
if (navBar) {
navBar = React.addons.cloneWithProps(navBar, {
navigator: navigator,
route: route
});
}
// Determine which Icon component - hamburger or back?
var customPrev = <MenuIcon leftButtonPress={this.onLeftButtonPress} />;
if (route.index > 0){
var customPrev = <BackIcon leftButtonPress={this.onLeftBackButtonPress} />;
}
// Done
return (
<View style={AppStyles.container}>
<NavigationBar
style={AppStyles.navbar}
customPrev={customPrev} />
<Component navigator={navigator} route={route} />
</View>
);
},
/**
* RENDER
*/
render: function() {
return (
<SideMenu
ref="rootSidebarMenu"
menu={<Menu events={this.eventEmitter} navigate={this.navigate} />}
touchToClose={this.state.touchToClose}
disableGestures={this.state.disableGestures}>
<Navigator
ref="rootNavigator"
style={[AppStyles.container, AppStyles.appContainer]}
renderScene={this.renderScene}
initialRoute={{
component: Index,
index: 0,
}} />
</SideMenu>
);
}
});
/* ==============================
Styles
=============================== */
var styles = StyleSheet.create({
});
And the code that pushes to the home page route looks like this:
//component that opens up app to login screen
var React = require('react-native');
var {
View,
Text,
StyleSheet,
Image,
TextInput,
} = React;
//additional libraries
var Parse = require('parse/react-native');
var ParseReact = require('parse-react/react-native');
var FBLoginManager = require('NativeModules').FBLoginManager;
var FBSDKCore = require('react-native-fbsdkcore');
var Actions = require('react-native-router-flux').Actions;
var { FBSDKGraphRequest, FBSDKGraphRequestManager } = FBSDKCore;
//dimensions
var Dimensions = require('Dimensions');
var window = Dimensions.get('window');
//dynamic variable components
var ImageButton = require('../components/imageButton');
module.exports = React.createClass({
componentWillMount: function(){
},
getInitialState: function() {
return {
username: '',
password: '',
errorMessage: '',
loadingCurrentUser: true,
};
},
render: function() {
return (
<View style={[styles.container]}>
<Image
style={styles.bg}
source={require('../img/login_bg1_3x.png')}>
<View style={[styles.header, this.border('red')]} >
<View style={styles.headerWrapper} >
<Image
style={[styles.login_brand]}
resizeMode={"contain"}
source={require('../img/login_brand_2.png')} />
<ImageButton
style={[styles.fb_btn]}
resizeMode={'contain'}
onPress={this.onFbLoginPress}
source={require('../img/fb_login.png')} />
<Image
style={[styles.loginBar]}
style={[styles.loginBar]}
resizeMode={'contain'}
source={require('../img/login_bar_3x.png')} />
</View>
</View>
<View style={[styles.footer, this.border('blue')]} >
<View style={styles.footerWrapper} >
<Text style={styles.error}>{this.state.errorMessage}</Text>
<TextInput
placeholder={'Email'}
style={styles.input}
value={this.state.username}
onChangeText={(text) => this.setState({username: text})} />
<TextInput
placeholder={'Password'}
style={styles.input}
secureTextEntry={true}
value={this.state.password}
onChangeText={(text) => this.setState({password: text})} />
<ImageButton
style={[styles.email_btn]}
resizeMode={'contain'}
onPress={this.onEmailLoginPress}
source={require('../img/email_login_btn.png')} />
<ImageButton
style={[styles.email_btn]}
resizeMode={'contain'}
onPress={Actions.pop}
source={require('../img/create_acct_btn.png')} />
</View>
</View>
</Image>
</View>
);
},
onFbLoginPress: function() {
},
onEmailLoginPress: function() {
//log the user on, get eror if login information doesn't exist
//we need to show the user that the error occured
Parse.User.logIn(this.state.username, this.state.password, {
success: (user) => {
Actions.home();
console.log("Successful Login!");
},
error: (data, error) => { this.setState({ errorMessage: error.message }); }
});
},
//function that helps with laying out flexbox itmes
//takes a color argument to construct border, this is an additional
//style because we dont want to mess up our real styling
border: function(color) {
return {
//borderColor: color,
//borderWidth: 4,
}
},
});
var styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'stretch',
},
bg: {
flex: 1,
width: window.width,
height: window.height,
},
header: {
flex: 2,
},
headerWrapper: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent:'space-around',
marginTop: window.height/35,
},
footerWrapper: {
flexDirection: 'column',
alignItems: 'center',
justifyContent:'space-around',
marginTop: 15,
},
footer: {
flex: 4,
},
loginBar: {
width: (window.width/1.3)/1.8,
height: (70/553)*((window.width/1.3)/1.8),
},
fb_btn: {
width: window.width/1.3,
height: (147/1095)*window.width/1.3,
margin: 10,
},
login_brand: {
width: window.width/6,
height: (268/273)*window.width/6,
margin: 6,
},
input: {
padding: 4, //gives us offset to border
height: window.height/20,
backgroundColor: 'rgba(255,255,255, 0.4)',
borderColor: 'gray',
borderWidth: 1,
borderRadius: 2, //round input box
margin: 2,
width: window.width/1.3,
alignSelf: 'center', //center yourself on form when you have fixed widths
},
email_btn: {
width: window.width/1.3,
height: (147/1095)*window.width/1.3,
margin: 3,
},
error: {
alignItems: 'center',
alignSelf:'center',
fontFamily: 'Bebas Neue',
fontSize: 15,
color:'red',
},
});
Finally, my app's routing structure in main looks like this:
//routing component to connect
//android and ios to same build
'use strict';
//component variables
var React = require('react-native');
var { Text, View, StyleSheet, Navigator} = React;
var Launch = require('./src/screens/launch');
var Signup = require('./src/screens/signup');
var Signin = require('./src/screens/signin');
var Introduction = require('./src/screens/introduction');
var Home = require('./src/screens/home');
//dynamic libraries
var SplashScreen = require('@remobile/react-native-splashscreen');
var Parse = require('parse/react-native');
var {Router, Route, Schema, Animations, TabBar} = require('react-native-router-flux');
module.exports = React.createClass({
componentWillMount: function() {
//executed when component shows on screen
//tells app to initialize parse and facebook js sdk
Parse.initialize("???", "???");
},
componentDidMount: function() {
SplashScreen.hide();
},
render: function() {
return (
<Router hideNavBar={true} initialRoutes={['launch']}>
<Schema name="bottom" sceneConfig={Navigator.SceneConfigs.FloatFromBottom}/>
<Schema name="right" sceneConfig={Navigator.SceneConfigs.FloatFromRight}/>
<Schema name="withoutAnimation"/>
<Route name="launch" component={Launch} wrapRouter={true} title="Launch" hideNavBar={true} schema="right"/>
<Route name="signin" component={Signin} title="Signin" schema="right"/>
<Route name="signup" component={Signup} title="Signup" schema="right"/>
<Route name="introduction" component={Introduction} title="Introduction" schema="right"/>
<Route name="home" component={Home} title="Home" schema="right"/>
</Router>
);
}
});
来源:https://stackoverflow.com/questions/34417144/create-a-side-menu-home-page-with-react-native-navbar-react-native-router-flux