Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change initial route after logging in #1878

Closed
Raktima opened this issue Jun 14, 2017 · 14 comments
Closed

Change initial route after logging in #1878

Raktima opened this issue Jun 14, 2017 · 14 comments

Comments

@Raktima
Copy link

Raktima commented Jun 14, 2017

I'm new in react native and currently developing a react-native app that require login.After successful login, the view change into Homepage. The problem is after i close and re-open the app, it shows me LoginPage again. Normally when you close some app that require login and re-open it, it will redirect to home page if you're already logged in. but in my case, it always show the LoginPage first.

How to change initial route to HomePage if the user has already logged after closing and re-open the app?

@jqn
Copy link

jqn commented Jun 14, 2017

You can use AsyncStorage persist the user as logged in and then check on component mount if the user is logged in. If true show Homepage instead of LoginPage

@matthamil
Copy link
Member

If you use @jqn's approach, I'd advise using some sort of splash screen component to do the check for you. That way, you can render the splash screen until the data is loaded from AsyncStorage. If you don't use some sort of a temporary splash screen, the user will see the login screen until AsyncStorage has loaded the cached data.

@Raktima
Copy link
Author

Raktima commented Jun 14, 2017

So right now I am not doing conditional rendering, instead I am nesting my routers something like this:

`
const Main=StackNavigator({
PhoneInputPage: { screen: PhoneInputPage },
OTP:{screen:OTP}
})

   const Routes = StackNavigator({

Login: { screen: Login },
Main:{screen: Main}
   },
 {
headerMode:'none'
  })`

So should I remove the current structure?

@WeIio
Copy link

WeIio commented Jun 15, 2017

Better experience is check whether logged in in root component,after that set initialRouteName with wanted component or screen.
Unfortunately, set initalRouteName is still not implemented, see #458 (comment) for more information

@Raktima
Copy link
Author

Raktima commented Jun 15, 2017

Can you give me an example as to how initialRouteName works?

@matthamil
Copy link
Member

matthamil commented Jun 15, 2017

@Raktima initialRouteName is not a feature of react-navigation at this time. It's not a solution to your problem right now.

I'd create a splash screen component something like so:

import LogIn from './LogInNavigator';
import Home from './HomeNavigator';

class SplashScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state ={ isLoggedIn: false };
  }

  componentDidMount() {
    AsyncStorage.getItem('loggedInStatus',
    (value) => {
      this.setState({ loggedInStatus: value });
    });
  }

  render() {
    if (this.state.loggedInStatus === 'loggedIn') {
      return <Home/>
    }
    else if (this.state.loggedInStatus === 'loggedOut') {
      return <LogIn screenProps={{ isLoggedIn: () => this.setState({ loggedInStatus: 'loggedIn' }) }}/>
    }
 
    return <SplashScreen/>
  }
}

Inside your LogIn screen, you could so something like:

class LogIn extends React.Component {
  constructor(props) {
    super(props);
  }

  logInUser() {
    // logic to log in user through your server/API/whatever
    this.props.screenProps.isLoggedIn(); // sets state in parent component which will now update and render Home
    // set logged in status in AsyncStorage
  }

  render() {
    return // login screen stuff
  }
}

Using this approach, I think LogIn really doesn't have to be a navigator.

@Raktima Raktima closed this as completed Jun 19, 2017
@Quixotical
Copy link

@matthamil thanks for the post, helped me solve my problem!

@amorenew
Copy link

My Full solution
#2683

@iamrutvik
Copy link

So basically redirecting user to the Home screen in nested navigator scenario, I did this little trick. As react-navigation does not provide a way to set the initialRouteName, we dispatch an action to navigate to the drawer stack i.e. Home screen.

Here is our Navigation file with Redux integration, which will show you the nesting of various navigators

// drawer stack
const DrawerStack = StackNavigator({
  DashboardScreen: { screen: DashboardScreen, navigationOptions: { title: 'Event', drawerLabel: 'Event' } },
  MyAccountScreen: { screen: MyAccountScreen, navigationOptions: { title: 'My Account', drawerLabel: 'My Account' } },
}, {
    headerMode: 'screen',
    navigationOptions: ({ navigation }) => ({
      headerStyle: {
        backgroundColor: Colors.darkBlue,
        shadowOpacity: 0,
        shadowOffset: { height: 0, },
        elevation: 0,
      },
      headerTitleStyle: {
        color: Colors.snow,
        alignSelf: 'center',
      },
      headerLeft: navigation.state.routeName == 'DashboardScreen' ? <TouchableOpacity activeOpacity={0.2} style={styles.leftIcon} onPress={() => {
        navigation.dispatch(NavigationActions.navigate({ routeName: 'DrawerOpen' }));
      }}><Image large source={Images.Bar} style={styles.bar} /></TouchableOpacity> : <TouchableOpacity activeOpacity={0.2} style={styles.leftIcon}
        onPress={() => {
          if (navigation.state.params && navigation.state.params.onBackPress) {
            navigation.state.params.onBackPress();
          }
          navigation.goBack();
        }}><Icon name="angle-left" size={28} color="snow" /></TouchableOpacity>,
      headerRight: <TouchableOpacity activeOpacity={0.2} style={styles.leftIcon} onPress={() => {
        navigation.dispatch(NavigationActions.navigate({ routeName: 'DrawerOpen' }));
      }}><Icon size={28} color="snow" /></TouchableOpacity>

    })
  })
const DrawerNavigation = DrawerNavigator({
    DrawerStack: { screen: DrawerStack }

}, {
    contentComponent: DrawerComponent,
    drawerWidth: 300,
  })
// login stack
const LoginStack = StackNavigator({
  LoginScreen: { screen: LoginScreen },
  RegisterScreen: { screen: RegisterScreen },
  ForgotPasswordScreen: { screen: ForgotPasswordScreen },
  CountryListScreen: { screen: CountryListScreen },
  VerificationScreen: { screen: VerificationScreen },
}, {
    headerMode: 'none',
  })
// Manifest of possible screens
const PrimaryNav = StackNavigator({
    drawerStack: { screen: DrawerNavigation },
    loginStack: { screen: LoginStack },
  }, {
    // Default config for all screens
    headerMode: 'none',
    initialRouteName:  'loginStack',
    transitionConfig: noTransitionConfig,
})
export default PrimaryNav

Now we have done a little bit tweak in the first App.js file which will run just after botting the React native application from index.ios.js/index.android.js/index.js file. We just set a state loading to check whether data is loaded from AsyncStorage or not. And if the data is loaded, then we will return our Root component else we will return null, which will not show login screen or anything on the UI front.

import '../Config'
import DebugConfig from '../Config/DebugConfig'
import React, { Component } from 'react'
import { Provider } from 'react-redux'
import RootContainer from './RootContainer'
import createStore from '../Redux'
import { AsyncStorage, Linking } from 'react-native'
import Constants from '../Components/Constants'
import LinkRoutes from '../Config/LinkRoutes';
import {NavigationActions} from 'react-navigation';

// create our store
const store = createStore()

/**
 * Provides an entry point into our application.  Both index.ios.js and index.android.js
 * call this component first.
 *
 * We create our Redux store here, put it into a provider and then bring in our
 * RootContainer.
 *
 * We separate like this to play nice with React Native's hot reloading.
 */
class App extends Component {

  constructor(props) {
    super(props)
    this.state = {
      loading: false,
    }
  }


  componentWillMount() {
    AsyncStorage.getItem(Constants.KEY_IS_LOGIN, (err, result) => {
      this.setState({ loading: true} , () => {
        if (result === '1') {
          const navigateAction = NavigationActions.navigate({
            routeName: 'drawerStack',
            index: 0,
          });
          store.dispatch(navigateAction);
        }
      })
    });
  }


  render() {
    if(this.state.loading){
      return (
        <Provider store={store}>
          <RootContainer />
        </Provider>
      )
    }else{
      return null
    }
  }
}

// allow reactotron overlay for fast design in dev mode
export default DebugConfig.useReactotron
  ? console.tron.overlay(App)
  : App

In componentWillMount I have just dispatched a NavigationActions that will navigate to the Drawer screen/Home screen. Hope this helps.

@dwivediamit
Copy link

Hi can you help me here...

/* @flow */

import React from "react";

import { Platform } from "react-native";
import { Root, StyleProvider } from "native-base";
import { StackNavigator } from "react-navigation";

import Artboard from "./src/artboard/Artboard";
import Login from "./src/artboard/Login";
import Signup from "./src/artboard/Signup";
import LocationMap from "./src/artboard/LocationMap";
import AvailablePlans from "./src/artboard/AvailablePlans";
import Checkout from "./src/artboard/Checkout";
import AddCard from "./src/artboard/AddCard";
import ActivityDetail from "./src/artboard/ActivityDetail";
import CalendarScreen from "./src/artboard/CalendarScreen";
import Confirmation from "./src/artboard/Confirmation";
import ForgotPassword from "./src/artboard/ForgotPassword";
import SuccessfullBooking from "./src/artboard/SuccessfullBooking";
import MainScreenNavigator from "./src/artboard/Index";

import getTheme from '../native-base-theme/components';
import material from "../native-base-theme/variables/material";
import platform from "../native-base-theme/variables/platform";

import Icon from 'react-native-fa-icons';

import commonColor from '../native-base-theme/variables/commonColor';

const AppNavigator = StackNavigator(
{

Artboard: { screen: Artboard
 //    navigationOptions: {
 //      headerLeft: null
 // },
},
Login: { screen: Login },
Signup: { screen: Signup },
MainScreenNavigator: { screen: MainScreenNavigator },
ForgotPassword: { screen: ForgotPassword },
LocationMap: { screen: LocationMap },
AvailablePlans: { screen: AvailablePlans },
Checkout: { screen: Checkout },
AddCard: { screen: AddCard },
ActivityDetail: { screen: ActivityDetail },
CalendarScreen: { screen: CalendarScreen },
Confirmation: { screen: Confirmation },
SuccessfullBooking: { screen: SuccessfullBooking },

},

{
initialRouteName: "Artboard",
headerMode: "none",
}
);

export default () =>

; how to change initialRouteName if logged in right now my initialRouteName Artboard if logged in then i want in place of Artboard it will go to home screen... please help

@Biplovkumar
Copy link

Biplovkumar commented Oct 14, 2018

  1. create a Swich navigator,then inside put 4 const stack navigator.

Artboard: { screen: Artboard} //for Auth check,user is logged in or not.
Login: { screen: Login }, //For login in
Signup: { screen: Signup },
AppNavigator ;{screen: Appnavigator }

2.your App navigator which initial screen is Home.

const AppNavigator = StackNavigator(
{

Home: { screen: Home},
MainScreenNavigator: { screen: MainScreenNavigator },
ForgotPassword: { screen: ForgotPassword },
LocationMap: { screen: LocationMap },
AvailablePlans: { screen: AvailablePlans },
Checkout: { screen: Checkout },
AddCard: { screen: AddCard },
ActivityDetail: { screen: ActivityDetail },
CalendarScreen: { screen: CalendarScreen },
Confirmation: { screen: Confirmation },
SuccessfullBooking: { screen: SuccessfullBooking },
},

{
initialRouteName: "Home",
headerMode: "none",
}
);

Now we have done ,thanks.

@medmo7
Copy link

medmo7 commented Aug 20, 2019

Well explained authentication flow exemple in https://reactnavigation.org/docs/en/auth-flow.html

@alishah514
Copy link

I'm new in react native and currently developing a react-native app that require login.After successful login, the view change into Homepage. The problem is after i close and re-open the app, it shows me LoginPage again. Normally when you close some app that require login and re-open it, it will redirect to home page if you're already logged in. but in my case, it always show the LoginPage first.

How to change initial route to HomePage if the user has already logged after closing and re-open the app?

Through This Approach
IN LOGIN SCREEN, AFTER SUCCESSFUL API CALL SAVE DATA IN ASYNCTORAGE

if (response.StatusCode === 200 && response.Message === 'Success') {
         storeData(Constants.BEARER_TOKEN, response.Result.Token.access_token);
         storeData(Constants.IS_LOGGED_IN, 'true');

IN SPLASH SCREEN PUT A CHECK IN UseEffect() HOOK


  useEffect(() => {
      getData(Constants.IS_LOGGED_IN).then(value => {
      console.log('Value UseEffect: ', value);
      setTimeout(() => {
        if (value === 'true') {
          navigation.navigate('Dashboard');
        } else {
          navigation.navigate('Login');
        }
      }, 2000);
    });
  }, [navigation]);

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests