How to load Home screen without showing login screen after login successful? - react-native

There are two stacknavigator for navigate with screens. I want to take condition for isloggedin or not. If loggedin user then select Appstack neither AuthStack. How to do this in this code? Is anyone can suggest me changes?
const AuthStack = createStackNavigator({
Welcome: {screen: WelcomeScreen,
navigationOptions: {
header:null
}},
Login: LoginScreen,
Signup: SignupScreen,
Forgot:ForgotScreen,
});
const AppStack =createStackNavigator(
{
Dashboard: DashboardScreen,
ScanScreen:ScanScreen,
});
export default createSwitchNavigator(
{
App:AppStack,
Auth:AuthStack,
},
{
initialRouteName:'Auth',
}
);

Where you define, and export your routers, define and export a function, which accepts a boolean parameter 'isLoggedIn', and returns the respective router, based on the value of isLoggedIn.
const AuthStack = createStackNavigator({
Welcome: {screen: WelcomeScreen,
navigationOptions: {
header:null
}},
Login: LoginScreen,
Signup: SignupScreen,
Forgot:ForgotScreen,
});
const AppStack =createStackNavigator(
{
Dashboard: DashboardScreen,
ScanScreen:ScanScreen,
});
// This is the function that does the work, it will render
// the either Auth or App router, based on if you're logged in.
export const createRootNavigator = (isLoggedIn = false) => {
if (isLoggedIn === false) {
return <AuthStack/>
} else {
return <AppStack/>
}
};
Then in your app component (or wherever you're rendering your router), we need to import this function, and pass into it whether or not the user is currently logged in.
'file-above.js' is the code above, i.e. the code you gave in your example as well.
Rough example below.
// We import the file
import {createRootNavigator} from './file-above.js'
class App extends Component {
constructor (props) {
super(props);
this.state({
// Switching this will switch your stack router.
loggedIn: false
});
}
render () {
const {loggedIn} = this.state;
// Here we're rendering the router, passing in the
// loggedIn variable from state, this will dictate if the
// Auth or App router is rendered.
return createRootNavigator(loggedIn);
}
}
What is missing here of course is the 'loggedIn' field on the app components state switching, play with the code above, changing the value of loggedIn via the constructor definition, then go hook up to your login form(s), etc.

Related

Authentication Flow in React Native

I'm having issue creating the authentication flow of my app. What I actually want is to navigate user conditionally based on their role.
By default, I have created an AuthStack which is basically a stackNavigator and it has a login page. Once user logs in, we receive user's role through a network request. Next I navigate him to a simple home page that returns nothing but switchNavigator based on his role. Here's the code for better clarity.
const AuthStack = createStackNavigator({
Login: {
screen: Login
},
SignUp: {
screen: SignUp
},
Home: {
screen: Home
}
},
{
initialRouteName: 'Login',
headerMode: 'none'
});
const AppContainer = createAppContainer(AuthStack);
const Navigation = () => {
return <AppContainer />
}
When user logs in, I redirect him to Home screen shown in above mentioned stack. Here's the code in Home screen:
const Home = (props) => {
const AppContainer = createAppContainer(RootNavigator(props.user.role))
return <AppContainer />
}
Here I create a new app container (which might be the bad practice, advice please). And RootNavigator is a helper function which returns a switchNavigator:
export const RootNavigator = (user) => {
return createSwitchNavigator({
Admin: {
screen: AdminDrawerNavigator
},
Reporter: {
screen: ReporterDrawerNavigator
}
},
{
initialRouteName: user === 'admin'? 'Admin': 'Reporter'
})
}
This all works fine but it seems switchNavigator doesn't seem to work correctly. If I press back button of hardware, it goes back to login page. Thank you for your time. Please suggest the possible solution.
Try to reset you history navigation :
NavigationActions.reset({
index: 1,
actions: [NavigationActions.navigate({
routeName: 'Admin'
}),
]
});

Dynamic route with React Navigation

I have a react native app running with react navigation 3.9 with 2 components Signup and Event:
export default class Signup extends React.Component {
}
export default class Event extends React.Component {
}
Also there is a splash component which retrieve local token.
Whenever there is a token retrieved from local drive, then the initial route is Event. Otherwise the it is Signup.
const stack = createStackNavigator ({
Event: Event,
Signup: Signup,
},{
InitialRouteName: InitRoute //<<either Event or Signup
})
const initScreen = createSwitchNavigator({
Splash: Splash,
App: stack,
})
export default createAppContainer(initScreen)
Here InitRoute needs to be set by checking local token which is retrieved in splash component. Dynamic routes is not very straight forward with react navigation. What is a good way to implement it with react navigation?
You can create dynamic routes based on the token. You'll need a screen that renders those two routes. Like
// app renders createStackNavigator with Event and Signup
const routes = {
Event: {
screen: Event,
navigationOptions: {
title: 'Event',
},
},
Signup: {
screen: Signup,
navigationOptions: {
title: 'Signup',
},
},
};
class App extends React.Component {
// creates dynamic routes
createDynamicRoutes = initiaRoute => {
return createAppContainer(
createStackNavigator(routes, {
initialRouteName: initiaRoute,
})
);
};
render() {
// get initial route from splash screen
// this.props.navigation.navigate('App', { init: 'init screen' });
const initiaRoute = this.props.navigation.state.params.init || 'Event';
// create routes and set initial route
const AppContainer = this.createDynamicRoutes(initiaRoute);
return <AppContainer />;
}
}
InitScreen navigator renders App and Splash
const InitScreen = createSwitchNavigator({
Splash: Splash,
App: App,
})
export default createAppContainer(InitScreen);
Demo

What React Lifecycle method should I use to check auth state in react navigation TabNavigator

I am building a react native element. The element will have 3 react-navigation TabNavigator as follows:
const MainNavigator = createBottomTabNavigator({
login: { screen: LoginPage },
signup: { screen: SignupPage },
main: { screen: HomePage},
},
{
navigationOptions: {
//tabBarVisible: false, // comment out for testing
},
lazyLoad: true
});
My HomePage is checking the auth on componentDidMount
class HomePage extends Component {
componentDidMount() {
const { isAuthenticated, navigation } = this.props;
console.log("home isAutenticated???>>", isAuthenticated);
if (!isAuthenticated) {
navigation.navigate('login');
}
}
.....
}
All the auth flow works fine until I enabled tabBar to be visible. When I click the home tab even after I log out, the homePage still show, without triggering the componentDidMount logic, makes me wonder if I should put the auth checking logic in some other lifecycle method? if so, which one?

Add Methods to createStackNavigator

I am looking to add methods to handle authentication to the Component Returned by createStackNavigator. How can I do this?
It seems like it would make sense to do it at this level as it is the component that holds the entire application.
There is something called a switch navigator in react-navigation which helps
you to select navigators based on the authentication of a user. For example, let us suppose you have two navigators, LoggedInNavigator and LoggedOutNavigator. You can use the SwtichNavigator to toggle between these navigators on the basis of authentication status.
However there is also another way to do this. That is to have 3 navigators; RootNavigator, LoggedInNavigator and LoggedOutNavigator. You can set the default route of the navigator by sending a var which specifies if the user is authenticated or not.
In App.js
import { CreateRootNavigator } from RootNavigator.js; // the below file
class App extends React.component {
render() {
const isAuthenticated = this._getAuthState(); // contains a boolean variable if user is authenticated or not
const RootNavigator = createRootNavigator(isAuthenticated)
return {
<RootNavigator />
}
}
}
export default App;
In RootNavigator.js
import { LoggedInNavigator } from "./LoggedInNavigation";
import { LoggedOutNavigator } from "./LoggedOutNavigation";
export const CreateRootNavigator = (loggedIn = false) => {
return createStackNavigator({
LoggedIn: {
screen: LoggedInNavigator,
navigationOptions: {
gesturesEnabled: false
}
},
LoggedOut: {
screen: LoggedOutNavigator,
navigationOptions: {
gesturesEnabled: false
}
}
},
{
headerMode: "none",
mode: "modal",
initialRouteName: loggedIn ? "LoggedIn" : "LoggedOut"
});
};

React native login state across entire app

My home screen exists of a StackNavigator which is inside a DrawerNavigator. Code:
const HomeNavigator = StackNavigator({
Index: { screen: ScreenHome },
Register: { screen: ScreenRegister },
});
const App = DrawerNavigator({
Home: { screen: HomeNavigator }
},{
contentComponent: (navigation) => <ScreenMenu navigation={navigation}/>
});
AppRegistry.registerComponent('ReactApp', () => App);
After logging in through a REST Service i want to pass the loggedIn state to all my other screens. But how should i do this? Should i declare a Authentication Component which will be passed to all the screens? Or is there another best practice for a global login state?
You could use redux for setting up a global state for the app.