Can a stack navigator have 2 different routes in react navigation - react-native

My project structure looks like this :
Tab navigator
|-Tab1
|-Tab2
|-stack navigator
|-login
|
screen1
|
screen2
|
screen3
|-Tab3
|-Tab4
I want my stack navigator route to start from screen1 once I enter the username and password for login screen. Is there any way we can achieve this?
Can we reroute/change the routes of stack navigator?

Use SwitchNavigator to change/reroute the screen stack
I'm not using React Navigation V2, you should check the doc if you need more information about RNV2
Here's an example TODO:
in router.js (handling screen):
const Tab = TabNavigator({
Customer : {
screen: Customer,
}
});
const TabLogged = TabNavigator({
Handyman: {
screen: Handyman,
}
});
// here's the key to handle which account is logged
export const Check = SwitchNavigator({
Auth: Auth,
Account1: Tab,
Account2: TabLogged
})
create Auth.js to check which account is logged or not:
class foo extends React.component{
componentWillMount(){
this.props.navigation.navigate(usertype == "isLoggedIn" ? 'Account2' : 'Account1');
}
render(){
<View>
<ActivityIndicator size="large" color="#0000ff" />
<StatusBar barStyle="default" />
</View>
}
}
and in your app.js or index.js :
class app extends Component{
render() {
return <check/>;
}
}

Related

react-native expo deep linking -how to get a shareable link of my app

Functional Requirement: As a user 1, I want to share the link of a my profile screen to anyone by whatsapp/sms/email so that when he clicks that link, he will navigate to my app's user profile screen.
In the app, my profile has a button "Share"
When I click "Share" button, I want the URL to be the link of the my profile screen.
Question:
How to get the URL from deep linking and pass it in Share function?
Technical requirement: From the documentation in expo and other similar question in stack overflow, my understanding is that I can achieve it by using deep linking functionality.
However I am still not clear how to do it.
Environment:
React native app using Expo
A.Content of App.js
A-1 Screen navigation: Search profile screen-->Search result screen-->Profiledetails screen
const Searchafterloginstack = createStackNavigator({
SearchhomePostlogin: { screen: SearchhomePostlogin },
SearchresultPostlogin: { screen: SearchresultPostlogin },
Profiledetails: { screen: Profiledetails },
});
A-2. Bottom navigator
const AppNavigator = createBottomTabNavigator({
Login: {screen: Loginstack},
});
A-3. Another Bottom navigator
const PostloginNavigator = createBottomTabNavigator({
Home: {screen: PostloginFeed},
Find: {screen: Searchafterloginstack}
});
A-4. Appcontainer
const AppContainer = createAppContainer(createSwitchNavigator(
{ Prelogin: AppNavigator,
Postlogin: PostloginNavigator,
},
{initialRouteName: 'AppNavigator'}
));
export default class App extends React.Component {
render() {
return <AppContainer />
}
};
=============================================
B. Profiledetails.js (Profiledetails screen with "Share" button)
Screen navigation: Search profile screen-->Search result screen-->Profiledetails screen
export default class Profiledetails extends React.Component {
onShareMessage= ()=> {
Share.share({
url: Need help to get from deep linking-to navigate to profiledetails screen,
})
}
render() {
return (
<View >
<Text > {this.state.Name} </Text>
<Button title="Share" onPress={this.onShareMessage}/>
</View>
)}
}

problem in logging out from drawer navigator

I am trying to logout from drawer navigator to go back to 'login' screen but not able to dod so
i have a stack navigator in app.js where i have added dashboad (i.e drawer navigator) and login also
from login i am able to navigate to dashboard but from dashboard which has a drawer navigator is not going back to login page
Login.js
checkLogin() {
const {username,password}=this.state
if(username=="user" && password=="user")
{
this.props.navigation.navigate('dashboard')
}
Dashboard.js
class Dashboard extends Component{
static navigationOptions ={
header:null,
}
}
onLogout = () => {
console.log('sign out');
this.props.navigation.navigate('login');
calling--
<TouchableHighlight underlayColor='lightgrey'activeOpacity={0.8}
onPress={this.onLogout}>
app.js
const MainNavigator = createStackNavigator({
Splash:Splash,
login: Login,
signup:Signup,
dashboard:Dashboard,
dealerDashboard:DealerDashboard
});
const App = createAppContainer (MainNavigator);

React native react-navigation drawer not opening

I am using react-navigation as the navigation package for my react native application. and have also installed and configured react-native-gesture-handler along with react-navigation as mentioned in the documentation.
The problem i am facing is that the drawer doesn't open at random times. mostly this occurs when user goes through along the main stack navigation and comes back to home to open the drawer. otherwise the drawer seems to be working without any issues.
this is how i have configured my navigation,
MAIN STACK NAVIGATION
const AppStack = createStackNavigator(
{
DrawerNav: DrawerNav,
Home: Home,
Notification: Notification,
HomeSearch: HomeSearch
}
DRAWER NAVIGATION
const MyDrawerNavigator = createDrawerNavigator(
{
Home: Home,
MyAccount: MyAccount,
ContactUs: ContactUs,
InviteFriend: InviteFriend,
Terms: Terms,
SignOut: SignOut
},
And the MAIN STACK also contains a few TAB STACK also,
I want to know why the drawer doesn't respond.
The Code i used to open the drawer was
this.props.navigation.openDrawer();
bu the above code gave
this.props.navigation.openDrawer() undefined
when ever the above crash i mentioned occurs
as a fix i used,
import { DrawerActions } from "react-navigation";
this.props.navigation.dispatch(DrawerActions.openDrawer())
the above code also stop working after a the user goes through the STACK navigation a few times, but doesn't give any errors on development.
This error occurs both on production as well as development
currently running
react native : 0.59.8
react : 16.8.3
react navigation: 3.9.1,
react-native-gesture-handler:1.1.0,
any help would be much appreciated,
Thanks in advance
Try wrapping all your stack navigation with Drawer navigation.
const StackNav = createStackNavigator({
Home: Home,
Notification: Notification,
HomeSearch: HomeSearch
}
Now wrap the above with Drawer navigation
const AppStack = createDrawerNavigator({
StackNav: {
screen: StackNav,
navigationOptions: {
drawerLabel: <Hidden />,
},
},
Home: Home,
MyAccount: MyAccount,
ContactUs: ContactUs,
InviteFriend: InviteFriend,
Terms: Terms,
SignOut: SignOut
});
Now the StackNav will be showing in the Drawer as one of the screens. So create a class and return null then pass it down to Drawer label.
class Hidden extends Component {
render() {
return null;
}
}
Now you'll be able to call the this.props.navigation.openDrawer(); anywhere on the app. Let me know if it works.
I think you can use another easy way to handle this problem :
You can use react-native-drawer that is available in this link now i'm going to show you how you can work with it :
AppStack :
const AppStack = createStackNavigator(
{
Home: Home,
Notification: Notification,
HomeSearch: HomeSearch
}
Home Navigation
const MyHomeNavigator = createStackNavigator(
{
Home: Home,
MyAccount: MyAccount,
ContactUs: ContactUs,
InviteFriend: InviteFriend,
Terms: Terms,
SignOut: SignOut
},
Now lets assume this is your HomePage :
HomePage
import Drawer from 'react-native-drawer'
import DrawerComponent from '../components/drawer'
export default class HomePage extends Component{
render() {
return (
<Drawer ref={(ref) => this._drawer = ref} content={<DrawerComponent {...this.props}/>} side='right' captureGestures openDrawerOffset={0.3} acceptTap>
//your home page components
</Drawer>
)
}
}
as you can see you can access to the drawer by this._drawer and here i will show you how does <DrawerComponent> like :
DrawerComponent :
export default class DrawerComponent extends React.Component {
navigateTo = (path) => {
this.props.navigation.navigate(path)
}
render(){
return(
<View>
<View>
<Item path='MyAccount' navigate = {this.navigateTo}/>
<Item path='ContactUs' navigate = {this.navigateTo}/>
<Item path='InviteFriend' navigate = {this.navigateTo}/>
//And you add all the item you need here with navigateTo function
</View>
<View>
//LogOut Section
</View>
</View>
)
}
}
This Works for me fine, I hope this works for you too.
Best regards .

react navigation how to go back to different stack

const HomeStack = createStackNavigator({
Home: HomeScreen,
});
const CarStack = createStackNavigator({
Booking: BookingScreen,
Confirm: ConfirmScreen
});
export default createBottomTabNavigator({
HomeStack,
CarStack,
});
export default class HomeScreen extends React.Component {
goTo(){
this.props.navigation.navigate('Confirm')
}
render() {
return (
<View style={css.container}>
<button onPress={this.goTo.bind(this)}>go to</button>
</View>
);
}
}
export default class ConfirmScreen extends React.Component {
goBack(){
this.props.navigation.goBack()
}
render() {
return (
<View style={css.container}>
<button onPress={this.goBack.bind(this)}>goback</button>
</View>
);
}
}
In home screen, when I click goto, it take me to confirmscreen, which is good.
But when I press go back, it takes me to booking screen instead of home screen. Which is bad.
It suppose to take me to home screen. What am i missing here?
You have to define 2 separate navigators and check user/guest in another component. like this:
Provider.js:
export default class Provider extends Component {
render() {
let {key, signedIn, checkedSignIn} = this.state
return(
<View>
{
checkedSignIn
? signedIn
? <App />
: <SignedOut />
: null
}
</View>
)
}
}
App.js:
export default createStackNavigator({
home: Home // sample
})
SignedOut.js:
export default createStackNavigator({
auth: Auth // sample
})
If you are using react-navigation v2.x or greater, directly use the navigate method to go to your Home screen.
Customize the back button behaviour and call this.props.navigation.navigate('Home') on the back button press in Confirmation screen. This will cause the desired effect.
Since react-navigation v2.0, the navigate action is less pushy. If the route you specify is already in the stack, then that screen will be opened, instead of pushing a new screen in stack by default.
Reference
Try this:
this.props.navigtion.goBack('Home')
I hope it help you.

React Navigation - How to pass data across different screens in TabNavigator?

I have a TabNavigator, and in each tab is a StackNavigator. Inside the StackNavigator, I have screens. The screens in each Tab do not call each other directly; the TabNavigator handles the screen changes when a tab is pressed.
In the first tab, if the user clicks a button, some data is created. If the user then navigates to the second Tab, I would like to pass this data to the screen in the second Tab.
Here is a demo of the code:
import React from 'react';
import { Button, Text, View } from 'react-native';
import {
createBottomTabNavigator,
createStackNavigator,
} from 'react-navigation';
class HomeScreen extends React.Component {
doIt = () => {
this.props.navigation.setParams({results: ['one', 'two']}); // <--- set data when user clicks button.
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
{/* other code from before here */}
<Button
title="Set Results"
onPress={this.doIt}
/>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
console.log(this.props.navigation); // <--- console out when user clicks on this tab
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings</Text>
</View>
);
}
}
const HomeStack = createStackNavigator({
Home: HomeScreen,
});
const SettingsStack = createStackNavigator({
Settings: SettingsScreen,
});
export default createBottomTabNavigator(
{
Home: HomeStack,
Settings: SettingsStack,
},
{
}
);
The this.props.navigation.state.params never gets the data results in the second Tab. There isn't even a key for it, so if I try to access this.props.navigation.state.params.results, it will be undefined.
This is confusing because I thought props.navigation is passed to all screens automatically.
How can I pass data from one screen to another through the TabNavigator, using just react-navigation? I have seen answers that say to use Redux, but I would not like to import another library if all I want is to keep some state across screens in different react navigators.
It may seem that this.props.navigation.state.params is only able to old one parameter? Possibly? Try this:
doIt = () => {
this.props.navigation.setParams({results: 'one'}); // <--- set data when user clicks button.
}
console.log(this.props.navigation.state.params.results);
Setting props did not work when passing data across different tabs. I even tried playing with AsyncStorage, trying to save and retrieve them in different tabs.
I ended up using Redux to save my states, and that has worked well so far.
I came across a similar problem. I had a multi page form that the client insisted on having each step be enclosed in a tab on a tab bar. I used the react navigation createMaterialTopTabNavigator to create the navigator and couldn't find an easy way to pass the form data between tabs.
What I end up doing was using react's Context API and wrapped the tab navigator in a root form container that provides the context value to the navigator and routes inside. Here is how I did it:
Root form container
// MultiScreenForm.js
imports...
import MultiScreenFormNavigator from './MultiScreenFormNavigator'
export const FormContext = React.createContext()
class MultiScreenForm extends Component {
constructor(props) {
super(props)
this.state = {
// formDataHere
formUpdaters: {
onToggleOptIn: this.handleToggleOptIn // example updater method
// other
}
}
}
handleToggleOptIn = () => {
// toggle opt in form data with this.setState
}
render() {
return (
<FormContext.Provider value={this.state}>
<MultiScreenFormNavigator />
</FormContext.Provider>
)
}
}
export default MultiScreenForm
Example form page
// ProfileForm.js
imports...
import { FormContext } from './MultiScreenForm'
class ProfileForm extends Component {
render() {
// FormContext.Consumer uses function as child pattern
return (
<FormContext.Consumer>
{ (context) => (
// our form can now use anything that we pass through the context
// earlier, we passed the root form's state including an updater
<button onPress={context.formUpdaters.onToggleOptIn} />
// ...
)
}
</FormContext.Consumer>
)
}
}
export default ProfileForm
Tab navigator
// MultiScreenFormNavigator.js
imports...
import ProfileForm from './ProfileForm'
import { createMaterialTopTabNavigator } from 'react-navigation'
const MultiScreenFormNavigator = createMaterialTopTabNavigator(
{
Profile: ProfileForm,
// AnotherForm: AnotherForm
},
// { navigator options here... }
)
export default MultiScreenFormNavigator
We then render the MultiScreenForm instead of the tab navigator directly.
This worked for me but I feel there should be an easier way to do this. I hope people who read this can share their approaches.
#tempomax
tried same with AsyncStorage but data came in with a delay.
Sometimes you don't need Redux if your app stays small.
So tried to find a way without Redux.
Here is what I came up with
I hope it's not too late to answer.
Solved it with NavigationEvents and setting params to Route.
The problem with tab is that you canĀ“t pass params to screen because navigation.navigate will be triggered automatically if createMaterialTopTabNavigator is swiped or clicked on non-active TabBar Button.
This can be solved with NavigationEvent like follow.
import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
const MyScreen = () => (
<View>
<NavigationEvents
onWillFocus={payload => console.log('will focus',payload)}
onDidFocus={payload => console.log('did focus',payload)}
onWillBlur={payload =>
/*
if screen is about to change this will be triggred
In screen 'MyScreen2' you can get it with navigation.params
*/
this.props.navigation.navigate('MyScreen2', { name: 'Brent' })
}
onDidBlur={payload => console.log('did blur',payload)}
/>
{/*
Your view code
*/}
</View>
);
export default MyScreen;
Now you can get the data in MyScreen2
/* 2. Get the param, provide a fallback value if not available */
const { navigation } = this.props;
const itemId = navigation.getParam('name', 'DefaultName');
const otherParam = navigation.getParam('otherParam', 'some default value');
If you are using React Native Navigation Version 5.x with a DrawerNavigation, you can do this using
in screen 1:
<Button
onPress={() => {
this.props.navigation.navigate(<ScreenNameOfDrawerScreen>,
{screen:'<ScreenNameInTabDrawer>',params:{your_json_Data}});
}} />
in screen 2:
............
render() {
if(this.props.route.params!=undefined){
if(this.props.route.params.your_json_Data!=null){
// Use this.props.route.params.your_json_Data. It is your json data.
}
}
return (
..............