1

React Native Navbar と React Native Router Flux の使用法を組み合わせて、RN アプリの作成を簡素化しようとしました。そうすることで、ナビゲーターを再度使用する必要があるホームページに到達するまで、React Native Router Fluxを介してルートを切り替えるポイントに到達しました。

その理由は、React Native Router Flux でこのようなものを作成することはまだ可能だとは思わないからです。私がやろうとしているのは、ログイン/サインアップ ページからホーム フィード ページへの簡単なトランジションを作成することです。もちろん、コンポーネントごとに異なるサイド メニューを作成する必要はないので、最初は React Native Starter App Repo で行われていることを模倣しました。しかし、ログイン画面からホーム画面 (基本的に React Native Starter App コード) に遷移しようとすると、次のエラーが発生します。

ここに画像の説明を入力

私のホームページのコードは次のとおりです (これもほとんど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',
    },
});

最後に、メインのアプリのルーティング構造は次のようになります。

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

0 に答える 0