使用React Native Navbar + React Native Router Flux创建一个侧面菜单主页

时间:2015-12-22 13:36:52

标签: javascript react-native react-router navigator hamburger-menu

我试图结合使用React Native Navbar& React Native Router Flux简化我的RN应用程序的制作。在这样做的时候,我已经到了一个点,我正在通过React Native Router Flux切换路由,直到我到达主页,我需要再次使用Navigator。

原因在于我不认为可以使用React Native Router Flux创建类似this的内容。我要做的是创建一个从登录/注册页面到主菜单页面的简单过渡,这些页面在侧面菜单之间导航。当然,您不希望在每个组件上创建不同的侧面菜单,因此我模仿了React Native Starter应用程序Repo中的操作。但是当我尝试从登录屏幕转换到主屏幕(本质上是React Native Starter应用程序代码)时,我收到以下错误:

enter image description here

我的主页代码如下(同样来自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({
  });

推送到主页路由的代码如下所示:

//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',
    },
});

最后,我在app中的应用程序的路由结构如下所示:

//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>
    );
  }
});

0 个答案:

没有答案