Search code examples
react-nativereact-navigationexporeact-navigation-drawer

Drawer navigation with top tabs after login


I've been trying to build an application which will goto login screen after splash. Once the user logs in, it should be directed to a screen which has drawer navigation and tabs in it. I've been trying to implement this using react native expo. It's working fine in expo. But once I generate an APK and try to use it, after logging in it redirects to splash and login without showing any content. I've been using react-navigation package for navigating between the screens

My Navigator.js:

import React from 'react';
import { createAppContainer, createDrawerNavigator, createStackNavigator } from 'react-navigation';
import SplashScreen from '../screens/SplashScreen';
import Screen1 from '../screens/Screen1';
import Screen2 from '../screens/Screen2';
import Screen3 from '../screens/Screen3';
import MainDrawer from '../common/MainDrawer';

const LoginNavigator = createStackNavigator({
    splash: SplashScreen
}, {
        headerMode: 'none',
        navigationOptions: {
            headerVisibile: false,
        }
    });

const DrawerNavigator = createDrawerNavigator({
    screen1: Screen1,
    screen2: Screen2,
    screen3: Screen3,

}, {
        initialRouteName: 'screen1',
        contentComponent: props => <MainDrawer {...props} />,
        drawerWidth: 350,
        headerMode: 'none',
        navigationOptions: {
            headerVisible: false,
        }
    });


const TotalNavigator = createStackNavigator({
    loginStack: { screen: LoginNavigator },
    drawerStack: { screen: DrawerNavigator },
}, {
        headerMode: 'none',
        initialRouteName: 'loginStack',
        navigationOptions: {
            headerVisible: false,
        }
    })

PrimaryNavigator = createAppContainer(TotalNavigator);


export default PrimaryNavigator;

My MainDrawer.js:

import React from 'react';
import { View, Text } from 'react-native';
import Image from 'react-native-remote-svg';

export default class MainDrawer extends React.Component {

    constructor(props) {
        super(props);
    }

    static navigationOptions = {
        header: null,
    };
    render() {
        return (
            <View style={{ width: '100%', height: '100%', backgroundColor: '#2C2663' }}>
                <View style={{ left: '7%', top: '10%' }}>
                    <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
                        <Image source={require('../assets/images/user_pic.svg')} />
                        <Text style={{ color: '#fff', fontSize: 25, flexDirection: 'row', left: '-28%', top: '10%' }}> SomeOne</Text>
                    </View>
                    <View style={{ width: '80%', borderBottomWidth: 1, borderBottomColor: '#C0C0C0', top: '20%' }} />
                    <Text style={{ color: '#C0C0C0', fontSize: 11, top: '30%' }}>
                        {`Some dummy text`}</Text>
                    <View style={{ flexDirection: 'row', justifyContent: 'space-between', top: '40%' }}>
                        <Image style={{ width: 30, height: 30 }} source={require('../assets/images/icon.svg')} />
                        <Text style={{ color: '#fff', fontSize: 20, flexDirection: 'row', left: '-40%', top: '10%' }}
                            onPress={() => this.props.navigation.navigate('screen1')}> Screen 1 </Text>
                    </View>
                    <View style={{ flexDirection: 'row', justifyContent: 'space-between', top: '50%' }}>
                        <Image style={{ width: 30, height: 30 }} source={require('../assets/images/icon2.svg')} />
                        <Text style={{ color: '#fff', fontSize: 20, flexDirection: 'row', left: '-42%', top: '10%' }}
                            onPress={() => this.props.navigation.navigate('screen2')}
                        > Screen 2</Text>
                    </View>
                    <View style={{ flexDirection: 'row', justifyContent: 'space-between', top: '60%' }}>
                        <Image style={{ width: 30, height: 30 }} source={require('../assets/images/icon3.svg')} />
                        <Text style={{ color: '#fff', fontSize: 20, flexDirection: 'row', left: '-16%', top: '10%' }}
                         onPress={() => this.props.navigation.navigate('screen3')}
                        > Screen 3</Text>
                    </View>

                </View>
            </View>);
    }
}

My SplashScreen.js:

import React from 'react';
import { Animated } from 'react-native';
import LottieView from 'lottie-react-native';
import LoginScreen from './LoginScreen.js';

export default class SplashScreen extends React.Component {

    constructor(props) {
        super(props);
        this.state = { isAnimationVisible: true, animationProgress: new Animated.Value(0) };
        this.homeScreen = this.homeScreen.bind(this);
    }

    static navigationOptions = {
        header: null,
    };

    componentDidMount() {
        Animated.timing(this.state.animationProgress, { toValue: 1, duration: 15000 })
            .start(() => this.setState(s => ({ ...s, isAnimationVisible: false })));
    }

    //Navigate to Home screen
    homeScreen() {
        this.props.navigation.navigate('drawerStack');
    }

    render() {
        if (this.state.isAnimationVisible) {
            const interpolation = this.state.animationProgress.interpolate({ inputRange: [0, 1], outputRange: [0, 1] });
            return (
                <LottieView
                    source={require('../assets/animations/splash.json')}
                    progress={interpolation}
                    autoPlay
                    loop={false}
                    resizeMode='cover'
                />
            );
        }
        else {
            return (<LoginScreen goToHome={this.homeScreen} />);
        }
    }
}

My LoginScreen.js:

import React from 'react';
import { View, Image, Text, TextInput, KeyboardAvoidingView, ActivityIndicator } from 'react-native';
import { Button } from 'native-base';
import loginStyles from '../styles/loginStyles';


class LoginScreen extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            email: '',
            password: '',

        };
        this.onButtonPress = this.onButtonPress.bind(this);
    }

    static navigationOptions = {
        header: null,
    };


    onButtonPress() {

        let Users = list of users;
        for (let i = 0; i < Users.length; i++) {
            if ((Users[i].username == this.state.email) && (Users[i].password = this.state.password)) {
                this.props.goToHome();
            }

    }



    render() {
        // On pressing login after giving credentials this.onButtonPress() is called

    }
}

export default LoginScreen;

Can someone pointout where the issue is and suggest a fix? Thanks in advance.


Solution

  • Instead of creating TotalNavigator as StackNavigator use SwitchNavigation instead at the root, like this:

    SwitchNavigator
    |
    |-SplashScreen   # Create this as single screen no need to create Stack, initial screen
    |
    |-LoginNavigator
    |
    |-DrawerNavigator
    
    

    Then in the LoginScreen just navigate to MainDrawer directly, it will handle the back press as well.