Dynamic route with React Navigation - react-native

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

Related

How to show TabNavigator only for some screens but not for others? - The component for route 'TabNavigator' must be a React component

User should go first to the Authentication screen and, once authenticated, he should be redirected to the Tab Navigation screens.
I tried the following approach, which didn't work. The error I got was - The component for route 'TabNavigator' must be a React component:
const AppNavigator = createStackNavigator(
{
Authentication: Authentication,
TabNavigator: TabNavigator
},
{
initialRouteName: "Authentication"
}
);
const TabNavigator = createBottomTabNavigator(
{
Profile: { screen: Profile },
Dashboard: { screen: Dashboard },
History: { screen: History }
},
{
initialRouteName: "Dashboard"
}
);
export default createAppContainer(AppNavigator);
How can I make this happen?
Thanks for your help.

How to navigate on specific screen from route directory in react native?

I am using react switch navigator from react-navigation library. I create a separate file router.js and call in my App.js. Now i am using react-native-firebase and from the app.js i need to navigate to specific screen. If anyone having an idea then please let me know here is my code:
App.js:
import Router from "./src/Router";
class App extends Component<Props> {
render() {
return (
<Router />
);
}
}
export default App;
Router.js
const AppSwitchNavigator = createSwitchNavigator({
InitialScreen: {
screen: InitialScreen
},
Login: {
screen: Login
},
Forgot: {
screen: Forgot
},
SuccessMessage: {
screen: SuccessMessage
},
App: AppStackDelivery,
AppR: AppStackRecipient,
}, {
initialRouteName: 'InitialScreen'
});
const Router = createAppContainer(AppSwitchNavigator);
export default Router;
From the push notification i am receiving id and i need to navigate to detail screen but i don't get anything to my router or initial screen please anyone having an idea then please share.
You should use the Deep link. And go to the path you want in onNotification.
Example
handleNotification () {
const path = "chat/Eric";
const prefix = Platform.OS === 'android'
? 'myapp://myapp/'
: 'myapp://'
const url = `${prefix}${path}`;
Linking.openURL(url).catch(err => console.error(err));
firebase.messaging().setBadgeNumber(0);
}

How to load Home screen without showing login screen after login successful?

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.

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?

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.