Hide header inside DrawerNavigator (react-navigation) - javascript

Hye..
I currently playing around react-navigation and trying to solve issue where header did not hide when Drawer open...
I hope anyone can share how to solve this buggy header..below I attached my code integration of DrawerNavigator inside StackNavigator.
const Home = DrawerNavigator({
HomeMenu: { screen: HomeMenu },
Messages: { screen: Messages },
Notifications: { screen: Notifications },
Badges: { screen: Badges },
Leaderboard: { screen: Leaderboard },
Profile: { screen: Profile },
Logout: { screen: Logout }
});
const MainActivity = StackNavigator({
Home: { screen: Home }
})
Thank you in advance!

You can hide header like:-
const Home = DrawerNavigator({
HomeMenu: { screen: HomeMenu,
navigationOptions: {
header:false, //hide header if not needed so whole screen slide
},
},
Messages: { screen: Messages },
Notifications: { screen: Notifications },
Badges: { screen: Badges },
Leaderboard: { screen: Leaderboard },
Profile: { screen: Profile },
Logout: { screen: Logout }
});
const MainActivity = StackNavigator({
Home: { screen: Home }
})

Use StackNavigator inside DrawerNavigator and set headerMode: 'none' to root StackNavigator
const MenuStackNavigator = StackNavigator({
Dashboard: {
screen: Dashboard,
navigationOptions: {
title: 'Dashboard',
}
},
});
const PagesStackNavigator = StackNavigator({...});
const DrawerNavigator = DrawerNavigator({
MenuStack: {
screen: MenuStackNavigator,
navigationOptions: {
drawer: () => ({
label: 'MenuStackNavigator',
})
},
},
Pages: {
screen: PagesStackNavigator,
navigationOptions: {
drawer: () => ({
label: 'PagesStackNavigator',
})
},
}
});
const AppNavigator = StackNavigator({
Drawer: { screen: DrawerNavigator },
}, {
headerMode: 'none',
});

I had the same issue (TabNav nested inside DrawerNav) and found a super easy fix I wanted to share! This issue is discussed here, in the repo for react-navigation. The fix that I implemented (on the screen you want to hide):
MAIN: {
screen: MainTabs,
navigationOptions: {
drawerLabel: () => null // to hide this header
},
},
Slightly different version:
static navigationOptions = {
drawerLabel: () => null
}
Hope this helps!

I found the ways, I just need to do the other way around..
Make DrawerNavigator as the root Navigator and put StackNavigator inside it.. then there will be no header when open the drawer

I was also playing around this problem and found out that StackNavigator has to be nested inside Drawer one, but there are a lot of issues about this solution like synchronizing active menu state inside drawer and card stack.
// Manifest of possible screens
const MenuButton = ({ navigation }) => (
<View>
<TouchableOpacity onPress={() => navigation.navigate('DrawerOpen')}>
<Icon name="bars" style={{color: 'white', padding: 10, marginLeft:10, fontSize: 20}}/>
</TouchableOpacity>
</View>
);
const Nav = StackNavigator({
StoriesScreen: {
screen: StoriesScreen,
navigationOptions: { title: 'Stories' }
},
LaunchScreen: { screen: LaunchScreen },
LoginScreen: {
screen: LoginScreen,
navigationOptions: { title: 'Login' }
}
}, {
navigationOptions: {
header: navigation => ({
style: styles.header,
left: <MenuButton navigation={navigation} />,
}),
}
})
const PrimaryNav = DrawerNavigator({
StoriesScreen: {
screen: Nav,
navigationOptions: { title: 'Stories' }
},
LaunchScreen: { screen: LaunchScreen },
LoginScreen: {
screen: LoginScreen,
navigationOptions: { title: 'Login' }
}
})

I too had the same issue and solved by add "headerMode":none in main StackNavigator.
Example:
const AppMainStack = DrawerNavigator({
ActivitiesScreen: {screen: ActivitiesScreen},
}, {
drawerPosition: 'right',
});
const AppNavigator = StackNavigator({
StartScreen: {screen: StartScreen},
EnterCodeScreen: {screen: EnterCodeScreen},
CreateAccountScreen: {screen: CreateAccountScreen},
ProfileSetupScreen: {screen: ProfileSetupScreen},
SignInScreen: {screen: AppMainStack},
}, {
headerMode: 'none',
});

Related

Not getting params in header

I'm not getting params to my header in main(homeStack) screen.
When I change createBottomTabNavigator with Home: {screen: Home}, not with Home: {screen: homeStack} than parameters are transferred to my header successfully in that screen. I don't know why this happens. PLease help me to get that user data to my header in Home screen.
Also, I want to have a different header in each of the tabs and I want to display data to header via params, which I put in login as:
navigation.navigate('Home', { user: user });
My app.js code:
const homeStack = createStackNavigator({
screen1: {
screen: Home,
navigationOptions: {
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
},
},
},{ initialRouteName: 'screen1'});
const Routes = createStackNavigator({
Login: {
screen: Login,
navigationOptions: {
header: null,
}
},
Main: {
screen: createBottomTabNavigator({
Home: { screen: homeStack },
Profile: { screen: Settings },
}, {
initialRouteName:'Home',
})
}
},{
initialRouteName: 'Login',
});
export default class App extends React.Component {
render() {
return (
<Routes />
);
}
}
Code in screen home where is header:
export default class Home extends React.Component {
static navigationOptions = ({ navigation, navigationOptions }) => {
console.log(navigationOptions);
console.log(navigation);
// Notice the logs ^
// sometimes we call with the default navigationOptions and other times
// we call this with the previous navigationOptions that were returned from
// this very function
/*return {
title: navigation.getParam('user', 'A Nested Details Screen'),
headerStyle: {
backgroundColor: navigationOptions.headerTintColor,
},
headerTintColor: navigationOptions.headerStyle.backgroundColor,
headerTitle: navigation.state.params.user.name,
}; */
return {
headerTitle: navigation.state.params.user.name,
}
};
render() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<Text>Changes you make will automatically reload.</Text>
<Text>Shake your phone to open the developer menu.</Text>
</View>
);
}
}

React native bottom navigation in main screen

I have 2 screens.
First one is Login screen(without header) where I have "createStackNavigation"
and second one is Main screen where I would like to have bottom navigation(2 tabs) with Header in each of these two tabs.
I did bottom navigation but custom header does not work at all...It's only basic header. Can anyone have some basic example of this? Or can help me with tutorial?
My code in app.js:
const RootStack = createStackNavigator(
{
Home: {
screen: Login,
navigationOptions: ({ navigation }) => ({
header: null,
}),
},
Main: MainScreen,
},
{
initialRouteName: 'Home',
headerMode: 'screen',
}
);
My code in "Main" screen:
export default createBottomTabNavigator(
{
Domov: {
screen: HomeScreen,
},
Dnevnik: Diary,
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Domov') {
iconName='home';
} else if (routeName === 'Dnevnik') {
iconName='ios-calendar';
}
return (
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
);
},
}),
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: 'white',
showLabel: false,
inactiveTintColor: '#4C2601',
style: {
backgroundColor: '#033D51',
},
},
});
Thank you
Add header: null in your navigationOptions in Main screen. You'll be able to add your custom header.

StackNavigator in TabNavigator in StackNavigator, TabNavigator switches to wrong tab

I'm currently facing an issue where my TabNavigator which is nested inside a StackNavigator is not opening in the initialRouteName that I define.
It's easiest to see this with an example so here we go:
Outermost (StackNavigator)
const RootStackNavigator = StackNavigator(
{
Main: {
screen: MainTabNavigator,
},
Login: {
screen: LoginScreen,
},
Splash: {
screen: SplashScreen
}
},
{
initialRouteName: 'Splash',
headerMode: 'float',
}
);
export default class RootNavigator extends React.Component {
componentDidMount() {
this._notificationSubscription = this._registerForPushNotifications();
}
componentWillUnmount() {
this._notificationSubscription && this._notificationSubscription.remove();
}
render() {
return (
<RootStackNavigator />
);
}
}
MainTabNavigator (TabNavigator):
const HomeStackNavigator = StackNavigator(
{
//Lots of screens.
},
{
initialRouteName: 'HomeScreen',
headerMode: 'none',
}
);
const BStackNavigator = StackNavigator(
{
//Lots of screens.
},
{
initialRouteName: 'BScreen',
headerMode: 'none',
}
);
const CNavigator = StackNavigator(
{
//Lots of screens
},
{
initialRouteName: 'CScreen',
headerMode: 'none',
}
);
const DStackNavigator = StackNavigator(
{
//Lots of screens.
},
{
initialRouteName: 'DScreen',
headerMode: 'none',
}
);
const EStackNavigator = StackNavigator(
{
//Lots of screens
},
{
initialRouteName: 'EScreen',
headerMode: 'none',
}
);
export default TabNavigator(
//Adds elements to the navigator at the bottom.
{
Home: {
screen: HomeStackNavigator
},
B: {
screen: BStackNavigator,
},
C: {
screen: CStackNavigator,
},
D: {
screen: DStackNavigator,
},
E: {
screen: EStackNavigator,
}
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused }) => {
const { routeName } = navigation.state;
let iconName;
switch (routeName) {
//define icons.
}
return (
<Ionicons
name={iconName}
size={24}
style={{ marginBottom: -3 }}
color={focused ? Colors.tabIconSelected : Colors.tabIconDefault}
/>
);
},
}),
tabBarOptions: {
inactiveBackgroundColor: '#4d5a8b',
activeBackgroundColor: '#4d5a8b',
showLabel: false,
initialRouteName: 'Home'
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false
}
);
What I'm expecting is for the app to initially go to the splash screen. Check if the user is signed in, yes they are, then go to the MainTabNavigator's initialRouteName but what actually happens is that it's initially loads in the Home tab, and then after about 2-3 seconds it flicks over to the D tab.
Note: One thing I have noticed is that I have some screens in multiple of the StackNavigators for the tabs, for example you can navigate to ScreenX from the BStackNavigator and the CStackNavigator.
Has anyone experienced this before and have a way of getting around it?
I'd really appreciate any help.
Thanks!
I think it is because the initialRouteName parameter is at the wrong place.
Example:
export default TabNavigator(
//Adds elements to the navigator at the bottom.
{
Home: {
screen: HomeStackNavigator
},
B: {
screen: BStackNavigator,
},
C: {
screen: CStackNavigator,
},
D: {
screen: DStackNavigator,
},
E: {
screen: EStackNavigator,
}
},
{
initialRouteName: 'Home', // SHOULD BE HERE
navigationOptions: ({ navigation }) => ({
...
}),
tabBarOptions: {
inactiveBackgroundColor: '#4d5a8b',
activeBackgroundColor: '#4d5a8b',
showLabel: false,
//initialRouteName: 'Home', SHOULD NOT BE HERE
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false
}
);
Doc:
TabNavigator API

Navigate to root tab screen inside a tabnavigator - React Navigation

I have been using react-navigation for a while now. When I tried referring to this Snack on Expo, I realised that if I navigate inside a tab, then I could not navigate back to Home Tab screen by pressing the Home button on the tabbar. I have to click on Back button that is present on the screen in order to navigate back to home.
Here is a piece of code:
const HomeStack = StackNavigator({
Home: { screen: HomeScreen },
Details: { screen: DetailsScreen },
});
const SettingsStack = StackNavigator({
Settings: { screen: SettingsScreen },
Details: { screen: DetailsScreen },
});
export default TabNavigator({
Home: { screen: HomeStack },
Settings: { screen: SettingsStack },
});
Referring to above code, if I click on Settings from the tabbar and then navigate to Details present inside that stack then I cant navigate back to Settings when I click on Settings again. I have to click on Back button that is present in the top section of the screen.
What is wrong here?
It would be a good idea to use unique names for every new route. React Navigation uses these names as unique keys to differentiate between routes. I see a Settings in your default TabNavigator, and also another Settings for your SettingsStack StackNavigator. Same for Details too. (Simply renaming might solve your issue too, not sure).
So taking your example (and renaming Settings to SettingsScreen),
const HomeStack = StackNavigator({
Home: { screen: HomeScreen },
Details: { screen: DetailsScreen },
});
const SettingsStack = StackNavigator({
SettingsScreen: { screen: SettingsScreen },
Details: { screen: DetailsScreen },
});
export default TabNavigator({
Home: { screen: HomeStack },
Settings: { screen: SettingsStack },
});
Now, to go back to SettingsScreen from Settings > Details, you might wanna try
dispatch(NavigationActions.navigate({
routeName: 'Settings',
action: NavigationActions.navigate({ routeName: 'SettingsScreen' })
}))
The idea is that in case of nested navigators, if you want to go back to another screen via the parent, you should call Navigations.navigate twice, in a nested manner.
It's in their docs somewhere. I'll try adding the link here for reference as soon as I find it.
The tab navigator buttons only switch between the shown views. Since you navigated within your stack navigator, that's what you're seeing.
If you want to add the functionality that the stack is reset every time the tab button is pressed, you can do that by providing your own tab component and then calling reset on the stack navigator.
createTopTabs = () => {
return(
<MaterialTopTabs.Navigator initialRouteName="Tab_Daily"
tabBarOptions={{
showIcon: true,
style: { backgroundColor: '#C4e672' },
labelStyle: { fontSize: 12, fontWeight: 'bold' },
/* tabStyle: { width: 100 }, */
tabStyle: { height: 50 },
}}>
<MaterialTopTabs.Screen
name="Tab_ToDoNote"
component={TabToDoNote}
options={
{
title: '',
/* tabBarLabel: "Daily", */
tabBarIcon: () =>
(
<Icons_SimpleLine
style={
[
{
color: 'red',
}
]
}
size={25}
name={'note'}
/>
)
}
}
/>
<MaterialTopTabs.Screen
name="Tab_Daily"
component={TabDaily}
options={
{
title: '',
tabBarLabel: "Daily",
tabBarIcon: () =>
(
<Icons_MaterialCommunity
style={
[
{
color: 'red'
}
]
}
size={18}
name={'calendar-today'}
/>
)
}
}
/>
<MaterialTopTabs.Screen
name="Tab_Monthly"
component={TabMonthly}
options={
{
tabBarLabel: "Monthly",
tabBarIcon: () =>
(
<Icons_MaterialCommunity
style={
[
{
color: 'red'
}
]
}
size={18}
name={'calendar-month-outline'}
/>
)
}
}
/>
<MaterialTopTabs.Screen
name="Tab_Yearly"
component={TabYearly}
options={
{
tabBarLabel: "Yearly",
tabBarIcon: () =>
(
<Icons_MaterialCommunity
style={
[
{
color: 'red'
}
]
}
size={18}
name={'calendar-multiple'}
/>
)
}
}
/>
</MaterialTopTabs.Navigator>
);
}

How to reset from drawer navigator to tab navigator in react native?

This is my current navigation
const MainNavigator = TabNavigator(
{
SignIn: {
screen: SignInScreen,
},
Home: {
screen: SubNavigator,
}
},
{
navigationOptions: {
tabBarVisible: false,
swipeEnabled: false
},
initialRouteName: 'SignIn',
lazy: true
}
);
const SubNavigator = DrawerNavigator(
{
Page1: {
screen: StackNavigator(
{
pageOne: {
screen: ScreenOne,
navigationOptions: ({ navigation }) => ({
title: 'One',
headerLeft: (
<TouchableOpacity onPress={() => navigation.navigate('DrawerOpen')}>
<IOSIcon name="ios-menu" size={30} />
</TouchableOpacity>
),
headerStyle: { paddingRight: 10, paddingLeft: 10 },
})
},
pageTwo: { screen: ScreenTwo },
camera: {
screen: CameraScreen,
navigationOptions: {
title: 'Camera'
}
},
qrscanner: {
screen: QRScanner,
navigationOptions: {
title: 'QR Scanner'
}
},
},
)
},
Profile: {
screen: ProfileScreen, // log out from here
},
},
{
contentComponent: SideMenu,
initialRouteName: 'Driver',
contentOptions: {
activeTintColor: '#e91e63'
}
}
);
I want to log out from Profile and reset it to SignIn. It is triggered by onPress.
Inside code for Profile I put function and render a text like this
/*.......*/
navigateToReset(route) {
const navigateReset = NavigationActions.reset({
index: 0, key: null, actions: [NavigationActions.navigate({ routeName: route })],
});
this.props.navigation.dispatch(navigateReset);
}
onButtonPressSignOut = () => {
this.navigateToReset('SignIn');
}
/*....*/
render () {
return(
<View>
<Text onPress={this.onButtonPressSignOut}>
Sign Out
</Text>
</View>
);
}
But this gave me error:
Error: There is no route defined for key SignIn.
Must be one of: 'pageOne', 'pageTwo', 'camera', 'qrscanner'
I have searched online and found several issue like this.
This is some of the issue I found : Issue1, Issue2 but it does not work for me.
Did I miss something in the above code?
Thank you for your help and suggestion.

Categories