React Native Navigation Drawer - Open page not in drawer - react-native

I am new to React Native development, so sorry if this seems obvious.
I have a new app that uses React Navigation Drawer as its main method of navigation. How can I have an onPress function within a page that navigates to a component that is not in my Navigation Drawer?
this.props.navigation.navigate('example') only seems to work for pages defined in the drawer.
My Drawer config:
const MyApp = createDrawerNavigator({
Interactive: {
screen: (props) => <Interactive {...props}
list={[
{ name: "First" },
{ name: "Second" },
{ name: "Third" },
{ name: "Fourth" },
{ name: "Fifth" },
{ name: "Sixth" },
{ name: "Seventh" },
{ name: "Eighth" },
]} />,
},
Settings: {
screen: SettingsScreen,
},
},
I am pressing a button within "Interactive" that should navigate to a component that is not include in the config above.

You can have multiple navigators inside your application (and usually this is the case), and actually every screen you want to navigate to should be defined inside a navigator. Every key in a navigator can be a single Screen or another navigator (Stack-, Drawer-, Tab- or SwitchNavigator).
const DrawerRoutes = createDrawerNavigator({
// your drawer navigator implementation ...
});
const MyApp = createSwitchNavigator(
{
Drawer: DrawerRoutes,
Example: YourScreen, // this would be the screen you want to navigator to
},
{
initialRouteName: 'Drawer'
}
);
And now you can navigate to YourScreen by simply calling this.props.navigation.navigate('Example') from within your Drawer.
In a react-navigation application it is not unusual to have a large combination of nested navigators, but there is always one root navigator.

Related

Trouble migrating React Navigation v4 Deep Link configuration to React Navigation v5

I'm having some trouble migrating my deep-link from React Navigation v4 to React Navigation v5. 😊
For context, my deep linking has been working perfectly in React Navigation v5 with a tab bar navigator and stack navigators in each tab.
Here's what that looked like:
const MainApp = createBottomTabNavigator(
{
DiscoverTabStack: { screen: DiscoverTabStack, path: "" },
GroupTabStack: { screen: GroupTabStack, path: "" },
ProfileTabStack: { screen: ProfileTabStack, path: "" },
},
);
const DiscoverTabStack = createStackNavigator(
{
Discover: { screen: DiscoverScreen, path: "discover" },
DetailedActivityFromDeepLink: {
screen: DetailedActivityFromDeepLinkScreen,
path: "discover/activites/:id",
},
}
With React Navigation v4, I'm able to successfully deep link into the app to the correct place. However, I'm having some trouble with React Navigation v5. Below is how I'm approaching it with Reach Navigation v5.
const Tab = createBottomTabNavigator();
const DiscoverStack = createStackNavigator();
const prefixes = Linking.makeUrl("myapp://");
const linking = {
prefixes: [prefixes],
config: {
screens: {
DiscoverStack: {
path: "",
screens: {
Discover: {
path: "discover",
},
DetailedActivityFromDeepLink: {
path: "discover/activites/:id",
parse: {
id: (id) => `${id}`,
},
},
},
},
},
},
};
const DiscoverScreens = ({ navigation, route }) => {
return (
<DiscoverStack.Navigator mode="card">
<DiscoverStack.Screen
name="Discover"
component={DiscoverScreen}
/>
<DiscoverStack.Screen
name="DetailedActivityFromDeepLink"
component={DetailedActivityFromDeepLinkScreen}
/>
</DiscoverStack.Navigator>
);
};
render() {
return (
<Container>
<NavigationContainer linking={linking}>
<Tab.Navigator>
<Tab.Screen
name="Discover"
component={DiscoverScreens}
/>
</Tab.Navigator>
</NavigationContainer>
</Container>
);
}
Unfortunately, the above is not working. What may be wrong with my approach? How does one deep-link into an app that has tab bars with stack navigators in each tab?
I'm sure that this is a challenge for the majority of apps out there, so it'll be awesome for some help!! Thanks in advance!
What may be wrong with my approach?
In your root navigator (Tab.Navigator), you call your screen Discover, but in the linking config, you have written DiscoverStack.
The linking config needs to have the same names as you have your screens.

How to implement Drawer and TabBar in StackNavigator

I always use react-native-router-flux for navigation, but on this project I need to use react-navigation and I got some troubles with it. I need to implement drawer and tabBar inside stack navigator.
Problems:
I use header component from native-base library but i can't open
drawer.
How to use my own customized component for drawer and tabBar?
Maybe I need to chage structure. I will consider any recommendations how to improve structure.
I used version 3 of react-navigation.
My code:
const AppStackNavigator = createStackNavigator({
loginFlow: {
screen: createStackNavigator({
intro: { screen: Intro },
login: { screen: Login },
registration: { screen: Registration },
}),
navigationOptions: {
header: null
}
},
mainFlow: {
screen: createStackNavigator({
MyDrawer: createDrawerNavigator({
Dashboard: {
screen: Home,
},
first: {
screen: first,
},
second: {
screen: second
},
third: {
screen: third
},
last: {
screen: last
}
}),
// settings: { screen: SettingsScreen },
someTab: {
screen: createBottomTabNavigator({
main: { screen: Home },
firsrTab: { screen: Screen1 },
secondTab: { screen: Screen2 },
thirdTab: { screen: Screen3 },
nextTab: { screen: Screen4 }
}),
navigationOptions: {
header: null
},
}
}),
navigationOptions: {
header: null
}
}
});
const AppContainer = createAppContainer(AppStackNavigator);
import React from 'react';
import { Header, Left, Icon, Right } from 'native-base';
const CustomHeader = (props) => {
return(
<Header>
<Left>
<Icon
name='menu'
onPress={() => {this.props.navigation.openDrawer()}}
/>
</Left>
</Header>
)
}
export { CustomHeader }
You might wanna consider the SwitchNavigator for the authentication flow instead of a Stack at the top as it replaces the routes so that you can never navigate back to the login/signup/splash once you get into the application and for accessing Tabs and Drawer inside stack/switch, you can wrap the Drawer inside your top level navigator and tab inside the drawer.
So you root navigation would look like this.
export default RootNavigation = createSwitchNavigator({
LoginScreen: {screen: LoginContainer},
Application: {screen: AppDrawer},
});
Your drawer navigator should be like the following:
const AppDrawer = createDrawerNavigator({
ApplicationTab: {screen: TabBar},
... other screen that you might want to use in drawer navigation.
}, {
contentComponent : (props) => <MyCustomDrawer {...props} />
});
and, Tab Navigator would be,
const TabBar = createBottomTabNavigator({
TabScreen1: {screen: Tab1},
... other tabs...
}, {
tabBarComponent : (props) => <MyTabBar {...props} />
});
If you put each of those navigators in single file then please do declare Tab before Drawer and Drawer before the Switch, else it would give errors.
In my experience, customising drawer navigator is very simple and fruitful but customising tab is not, there aren't proper API doc for the same and community answers are also somewhat misleading.
BUT, with normal use cases and for most of the vivid ones too, you can do your job without needing to override the default one as it is already highly operable and customisable in terms of icons, materialism and each tab exposes its on onPress that can also be easily overriden.
and as you as the drawer is not getting operated from/via the header, then can you please ensure that the navigation prop you are using to operate the drawer open close or toggle action is the one given by drawer ?

React navigation unable to navigate to just pervious screen after navigating multiple screens

Scenario:
Navigate: Screen 'StoreCategories' --> Screen 'QRScanner'
Back press while at Screen 'QRScanner' redirect to Screen 'StoreCategories' working perfectly
Navigate: Screen 'QRScanner' --> Screen 'Options' and
Navigate: Screen 'Options' --> Screen 'QRScanner' again
Click on back while at Screen 'QRScanner' redirect to Screen 'StoreCategories' again
Not redirecting to its previous Screen 'Options'.
Everything happens with default back functioning in react-navigation, I am not using any custom function for back functioning.
How can I resolve it and navigate to just previous from redirection happens rather than already cached screen in react-navigation(V2)?
const StackNavigator = defaultRoute =>
createStackNavigator(
{
CustomerLogin: {
screen: CustomerLogins
},
MerchantLogin: {
screen: MerchantLogin
},
Profile: {
screen: Profile
},
OtpVerification: {
screen: OtpVerification
},
StoreOffers: {
screen: StoreOffers
},
StoreCategories: {
screen: StoreCategories
},
QRScanner: {
screen: QRScanner
},
MerchantHome: {
screen: MerchantHome
},
CustomerHome: {
screen: CustomerHome
},
ThankYou: {
screen: ThankYou
},
Detail: {
screen: Detail
},
Options: {
screen: Options
},
PayOnline: {
screen: PayOnline
},
PayCash: {
screen: PayCash
},
PayTm: {
screen: PayTm
},
Token: {
screen: Token
},
AddDiscount: {
screen: AddDiscount
},
CustomerHistory: {
screen: CustomerHistory
},
Webview: {
screen: Webview
},
Direction: {
screen: Direction
}
},
{
initialRouteName: defaultRoute
}
);
The way the current React-Navigation's navigate function works is a bit different then how they work previously. Currently if you navigate to a screen that is already in the screen stack, the system would go back to that screen (removing the other screens between the current screen and that screen will be remove) instead of simply adding a new screen to the stack.
If you want to use the old system style, you can use push instead of navigate. This would simply add to the stack instead of going back to the last one (if exist in the stack).
So rather than use
const {navigate} = navigation;
navigate(nextScreen, params);
you use
const {push} = navigation;
push(nextScreen, params);
if You want to navigate to back screen, you can use this code:
this.props.navigation.goBack()
by navigate to Main it will redirect to initial route of Main and it seems to be A

React Native (Android) - Stacknavigator above other view

I'm beginning in React Native development.
I've spend many hours on something but I'm still blocked.
I have a "header" view and under the view, a Stack navigator and inside a tab navigator.
When I open the stack navigator (with the Login Button), I would like to put the new view above the "header", without hiding him to avoid ugly effect when the new view appears.
Here an example when I put a negative margin top on the stacknavigator, but it stays behind the header
Is there any other way to do this properly ?
Thanks.
For information, I've started from the React Native boilerplate "Pepperoni App Kit", added my custom header before the AppNavigator, and hidden the headers on the Tab navigator.
Instead of having header under View, you should have use headerMode:'screen' option with StackNavigator. You can control the visibility of header under each sub navigator using the navigation options.
Here is sample snippet
export const Root = StackNavigator(
{
Tabs: {
screen: HOViewPager,
navigationOptions: {
title: "Title",
header: <Header />,
},
},
login: {
screen: Login,
navigationOptions: {
headerMode: "none",
header: null,
},
},
imageoverlay: {
screen: HOImageOverlay,
navigationOptions: {
headerMode: "none",
header: null,
},
},
},
{
mode: "modal",
headerMode: "screen",
}
);

How do i make a TabNavigator button push a modal screen with React Navigation

Using the React Navigation tab navigator https://reactnavigation.org/docs/navigators/tab how do I make one of the tab buttons push the screen up as a full screen modal? I see the stack navigator has a mode=modal option. how do I get that mode to be used when clicking on the TakePhoto tab button? Clicking on it currently still shows the tab bar on the bottom.
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
TakePhoto: {
screen: PhotoPickerScreen, // how can I have this screen show up as a full screen modal?
},
});
Actually, there is no support in react-navigation to change the way of presentation on the fly from default to modal (see the discussion about this here). I ran into the same issue and solved it by using a very top StackNavigator with headerMode set to none and mode set to modal:
const MainTabNavigator = TabNavigator(
{
Tab1Home: { screen: Tab1Screen },
Tab2Home: { screen: Tab2Screen }
}
);
const LoginRegisterStackNavigator = StackNavigator({
Login: { screen: LoginScreen }
});
const ModalStackNavigator = StackNavigator({
MainTabNavigator: { screen: MainTabNavigator },
LoginScreenStackNavigator: { screen: LoginRegisterStackNavigator }
}, {
headerMode: 'none',
mode: 'modal'
});
This allows me to do the following (using redux) in Tab1Screen and Tab2Screen to bring up the modal view from wherever I want:
this.props.navigation.navigate('LoginScreenStackNavigator');
Not sure if this is still relevant for you, but i've managed to find away to achieve this.
So i've managed to get it working by using the tabBarComponent inside the tabNavigatorConifg, you can stop the tab navigation from navigating depending on the index.
tabBarComponent: ({jumpToIndex, ...props, navigation}) => (
<TabBarBottom
{...props}
jumpToIndex={index => {
if (index === 2) {
navigation.navigate('camera')
}
else {
jumpToIndex(index)
}
}}
/>
)
Once you've done this, my method of showing the view modally on top of the tab views was to put the tabnavigator inside of a stacknavigatior and then just navigate to a new screen inside of the stacknavigator.
react-navigation's bottomTabNavigator has a tabBarOnPress navigation option you can use to override tab presses:
https://reactnavigation.org/docs/en/bottom-tab-navigator.html#tabbaronpress
const AppContainer = createStackNavigator(
{
default: createBottomTabNavigator(
{
TAB_0: Stack0,
TAB_1: Stack1,
TAB_2: Stack2,
TAB_3: View // plain rn-view, or any old unused screen
},
{
defaultNavigationOptions: {
// other tab navigation options...
tabBarOnPress: ({ navigation, defaultHandler }) => {
if (navigation.state.key === 'TAB_3') {
navigation.navigate('tabToOpenAsModal');
} else {
defaultHandler();
}
}
}
}
),
tabToOpenAsModal: {
screen: TabToOpenAsModalScreen
}
},
{
mode: 'modal',
headerMode: 'none'
}
);
If you nest your tab navigator within a stack navigator with a modal, you can open this when the tab bar button is pressed. Since the modal was opened and not the tab, when the modal is closed the app returns to the screen that was visible before the modal tab was pressed.
One way to make the tab bar go away is to hide the tabBar with visible: false:
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
TakePhoto: {
screen: PhotoPickerScreen,
navigationOptions: {
tabBar: {
visible: false,
},
},
},
});
However, that does not seem to trigger any transition to fullscreen, which I guess is desired?
Another option could be to wrap PhotoPickerScreen inside a new StackNavigator and set that navigator to mode='modal'.
You might have to trigger the navigation to that modal from onPress on the tabItem somehow (eg. navigation.navigate('TakePhoto').)
Note, I'm trying to wrap my head around how best to structure navigation myself, so …
Third option, implementing a StackNavigator as parent, then adding the MyApp TabNavigator as the first route inside of it, could be the most flexible solution. Then the TakePhoto screen would be on the same level as the TabNavigator, allowing you to route to it from wherever.
Interested to hear what you come up with!
I suggest two solution
First one is about hide it
For seconde one please read that: https://reactnavigation.org/docs/hiding-tabbar-in-screens
<Tab.Screen
name={Routes.CREATE_ANNOUNCEMENT_SCREEN}
// name={Routes.TEST_SCREEN}
options={{
.
.
.
tabBarVisible: false, <----- solution 1
tabBarButton: (props) => ( <----- or solution 2
<TouchableOpacity
{...props}
onPress={() => {
navigation.navigate(Routes.DETAILS_SCREEN);
}}
/>
),
}}
component={CreateAnnouncementScreen}
/>
Docs are patchy in some areas, but here it is:
export default class HomeScene extends Component {
static navigationOptions = {
title: 'foo',
header:{
visible: true
}
}
....
}