React-Navigation with Login Screen

后端 未结 10 2760
野性不改
野性不改 2020-11-28 19:30

I am trying to use react-navigation to create a initial LOGIN screen which has no tabbar and header, and once the user has been successfully authenticated will navigate to a

相关标签:
10条回答
  • 2020-11-28 19:45

    Its good that you are using react-navigation which has a good support for most of the features your app requires. Heres my advice

    1) On Authentication

    React-native has this nice feature state variables which when changed views are re-rendered. You can use state variables to understand the "state" (authenticated/visitor) of the users of your app.

    Here is a simple implementation where a user logs in by pressing a login button

    Entry page where user logs in

    import React from 'react';
    
    import Home from './layouts/users/home/Home';
    import Login from './layouts/public/login/Login';
    
    
    class App extends React.Component {
    
        state = {
            isLoggedIn: false
          }
    
        componentDidMount() {
            //Do something here like hide splash screen
        }
    
        render(){
            if (this.state.isLoggedIn)
             return <Home
    
                 />;
         else
             return <Login
             onLoginPress={() => this.setState({isLoggedIn: true})}
                 />;
    
        }
    }
    
    export default App;
    

    2) Login with header

    Login View

    import React from 'react';
    //Non react-native import
    import { TabNavigator } from 'react-navigation'
    import Icon from 'react-native-vector-icons/MaterialIcons'
    import LoginStyles from './Style'
    //Do all imports found in react-native here
    import {
        View,
        Text,
        TextInput,
        StyleSheet,
        TouchableOpacity,
    } from 'react-native';
    
    
    class Login extends React.Component {
      render(){
    
             return (
           <View>
           <Text>
             Login area
           </Text>
    
           <TouchableOpacity
                    style={LoginStyles.touchable}
                    onPress={this.props.onLoginPress}   >
    
                    <Text style={LoginStyles.button}>
                   Login
                    </Text>
                    </TouchableOpacity>
    
    
    
           </View>
         );
    
        }
    }
    
    export default Login;
    

    Remember to remove the style attributes in the login screen and add yours including import, I am leaving them there as it can help you have and idea how you can arrange you react project

    However it still works without the styles so you can take them off, clicking the login button will take you to the Home screen, since the state changed and the view has to be re-rendered according to new state

    The login screen is without a header as you required

    Home screen with tabs

    3) Tabs with header The general method to achieve this functionality it to add a TabNavigator in a StackNavigator.

           import React from 'react';
        import {
         DrawerNavigator,
         StackNavigator,
         TabNavigator,
         TabBarBottom,
         NavigationActions
        } from 'react-navigation'
        import Icon from 'react-native-vector-icons/MaterialIcons'
     
        
        //Do all imports found in react-native here
        import {
            View,
            Text,
            TextInput,
            StyleSheet,
            TouchableOpacity,
        } from 'react-native';
        
    class PicturesTab extends React.Component {
      static navigationOptions = {
        tabBarLabel: 'Pictures',
        // Note: By default the icon is only shown on iOS. Search the showIcon option below.
        tabBarIcon: ({ tintColor }) =>  (<Icon size={30} color={tintColor} name="photo" />),
      };
    
      render() { return <Text>Pictures</Text> }
    }
    
    class VideosTab extends React.Component {
      static navigationOptions = {
        tabBarLabel: 'Videos',
        tabBarIcon: ({ tintColor }) =>  (<Icon size={30} color={tintColor} name="videocam" />),
      };
    
      render() { return <Text>Videos</Text> }
    
    }
        
        const HomeTabs = TabNavigator({
          Pictures: {
            screen: PicturesTab,
          },
          Videos: {
            screen: VideosTab,
          },
        }, {
            tabBarComponent: TabBarBottom,
            tabBarPosition: 'bottom',
            tabBarOptions: {
            //Thick teal #094545
            activeTintColor: '#094545',
            showLabel: false,
            activeBackgroundColor: '#094545',
            inactiveTintColor: '#bbb',
            activeTintColor: '#fff',
        
        
          }
        });
        
        
        
        const HomeScreen = StackNavigator({
          HomeTabs : { screen: HomeTabs,
            navigationOptions: ({ navigation }) => ({
            // title :'title',
            // headerRight:'put some component here',
            // headerLeft:'put some component here',
             headerStyle: {
               backgroundColor: '#094545'
             }
        
        
           })
         },
        });
        
       
        
        
        export default HomeScreen;
    

    Disclaimer : Code may return errors as some files may be missing or some typos may be present you should check for details carefully and change where neccesary if you have to copy this code. Any problems can be pasted as comments. Hope this helps someone.

    You may also remove the icons in the tab configurations or install the react-native-vector icons which makes tabs great!

    0 讨论(0)
  • 2020-11-28 19:47

    this is how I achived this functionality.

    File 0)index.android.js

    'use strict'
    
    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View
    } from 'react-native';
    
    import Root from 'src/containers/Root'
    
    
    AppRegistry.registerComponent('Riduk', () => Root);
    

    File 1)my Root.js

    class Root extends Component {
        constructor(props) {
          super(props);
          this.state = {
            authenticated:false,
            isLoading:true,
            store: configureStore(() => this.setState({isLoading: false})),
          };
      }
    
      componentDidMount() {
        //you can do check with authentication with fb, gmail and other right here
       /* firebase.auth().onAuthStateChanged((user) => {
          if (user) {
            api.resetRouteStack(dispatch, "UserProfile");
            console.log("authenticated", user);
          } else {
            api.resetRouteStack(dispatch, "Landing");
            console.log("authenticated", false);
          }
        });*/
    
      }
    
      render() {
        if (this.state.isLoading) {  //checking if the app fully loaded or not, splash screen can be rendered here
            return null;
          }
          return (
    
            <Provider store={this.state.store}>
              <App/>
            </Provider>
    
          );
      }
    }
    module.exports = Root;
    

    2)App.js

    import AppWithNavigationState,{AppBeforeLogin} from './AppNavigator';
    
    class App extends Component{
        constructor(props){
            super(props);
        }
    
        render(){
            let {authenticated} = this.props;
            if(authenticated){
                return <AppWithNavigationState/>;
            }
            return <AppBeforeLogin/>
    
    
        }
    }
    
    export default connect(state =>({authenticated: state.user.authenticated}))(App);
    

    3)AppNavigator.js

    'use strict';
    
    import React, {Component} from 'react';
    import { View, BackAndroid, StatusBar,} from 'react-native';
    import {
      NavigationActions,
      addNavigationHelpers,
      StackNavigator,
    } from 'react-navigation';
    import { connect} from 'react-redux';
    
    import LandingScreen from 'src/screens/landingScreen';
    import Login from 'src/screens/login'
    import SignUp from 'src/screens/signUp'
    import ForgotPassword from 'src/screens/forgotPassword'
    import UserProfile from 'src/screens/userProfile'
    import Drawer from 'src/screens/drawer'
    
    
    
    const routesConfig = {
      //Splash:{screen:SplashScreen},
      Landing:{screen:LandingScreen},
      Login: { screen: Login },
      SignUp: { screen: SignUp },
      ForgotPassword: { screen: ForgotPassword },
      UserProfile:{screen:UserProfile},
    };
    
    
    export const AppNavigator = StackNavigator(routesConfig, {initialRouteName:'UserProfile'}); //navigator that will be used after login
    

    export const AppBeforeLogin = StackNavigator(routesConfig); //naviagtor for before login

    class AppWithNavigationState extends Component{
      constructor(props) {
        super(props);
        this.handleBackButton = this.handleBackButton.bind(this);
      }
    
      componentDidMount() {
        BackAndroid.addEventListener('hardwareBackPress', this.handleBackButton);
      }
    
      componentWillUnmount() {
        BackAndroid.removeEventListener('hardwareBackPress', this.handleBackButton);
      }
    
      //added to handle back button functionality on android
      handleBackButton() {
        const {nav, dispatch} = this.props;
    
        if (nav && nav.routes && nav.routes.length > 1) {
          dispatch(NavigationActions.back());
          return true;
        }
        return false;
      }
    
      render() {
        let {dispatch, nav} = this.props;
    
        return (
              <View style={styles.container}>
                {(api.isAndroid()) &&
                  <StatusBar
                      backgroundColor="#C2185B"
                      barStyle="light-content"
                  />
                }
                <AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav })}/>
              </View>
        );
      }
    };
    export default connect(state =>({nav: state.nav}))(AppWithNavigationState);
    //module.exports = AppWithNavigationState;
    
    0 讨论(0)
  • 2020-11-28 19:47

    There is now good documentation on the react-navigation site about the authentication flow.

    0 讨论(0)
  • 2020-11-28 19:52

    Although what Manjeet suggests will work, it is not a good navigational structure.

    What you should do is take a step back and handle everything on another level.

    Top level navigator should be a stack navigator that renders a login screen. Another screen within this top-most navigator should be your app's Main-Navigator. When your login state is satisfied, you reset the main stack to just the Main-Navigator.

    The reason for this structure is:

    A- What if you need to add on-boarding information before the Login the future?

    B- What if you need to navigate outside of the Main-Navigation environment (eg: your main nav is tabs and you want a non-tab view)?

    If your top-most navigator is a Stack-Navigator that presents Login screens and other Navigators, then your app's navigation structure can properly scale.

    I do not believe the conditional rendering of a login screen or stack navigator, as suggested above, is a good idea....trust me...I've gone down that road.

    0 讨论(0)
  • 2020-11-28 20:00

    Make tabbar and header separate components and only include them in other components. About disabling "BACK", there is a section about "blocking navigation actions" in the docs: https://reactnavigation.org/docs/routers/

    You should be able to use that for screen 2.

    0 讨论(0)
  • 2020-11-28 20:02

    If you want no back button from your LIST page to LOGIN page, you can do this:

        static navigationOptions = {
            title: 'YOUR TITLE',
            headerLeft : null,
        };
    
    0 讨论(0)
提交回复
热议问题