Search code examples
react-nativereact-navigationnavigation-drawerstack-navigator

Use the main App Header for Nested StackNavigation


I'm working on a React Native App, which I have on the main App.js file created a Drawer and a Stack Navigatior, the problem that I'm facing is that when I navigate through the Drawer to the Pages with the Stack Navigation, I get 2 Headers (one below the Other), is there a way to use the same header (top header or Main header) when I get to the Stack Pages.

Here is the App.js code:

import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { createStackNavigator } from '@react-navigation/stack';

//Importacion de Screens
import HomeScreen from './src/screens/HomeScreen';
import DetailsScreen from './src/screens/DetailScreen';
import OrderSearchScreen from './src/screens/OrderSearchScreen';
import OrderNumberScreen from './src/screens/OrderNumberScreen';

const OrderStack = createStackNavigator();
const Drawer = createDrawerNavigator();

const OrderStackScreen = () =>(
  <OrderStack.Navigator screenOptions={{
    headerStyle: {
        backgroundColor: '#009387',
      },
      headerTintColor: '#fff',
      headerTitleStyle:{
        fontWeight: 'bold',
      } ,
      headerTitleStyle: { alignSelf: 'center' },
      /*headerShown: false*/      
}}>
    <OrderStack.Screen name="OrderSearchScreen" component={OrderSearchScreen}/>
    <OrderStack.Screen name="OrderNumberScreen" component={OrderNumberScreen}/>
</OrderStack.Navigator>
);
 
export default function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator initialRouteName="Home" screenOptions={{
        headerStyle: {
          backgroundColor: '#009387',
        },
        headerTintColor: '#fff',
        headerTitleStyle:{
          fontWeight: 'bold',
        } ,
        headerTitleStyle: { alignSelf: 'center' },
      }}>
        <Drawer.Screen name="Home" component={HomeScreen} />
        <Drawer.Screen name="Details" component={DetailsScreen} />
        <Drawer.Screen name="Orders" component={OrderStackScreen} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Here is what I see inside the Stack:

2 Headers Error

What I wish to see is that the top Header Changes and the Bottom one never appears, so the Top Header will have the Title of the Page being visited and right next to the Drawer Icon (the 3 lines, I think it is called Hamburger button), I get the Arrow to go back.

Is there a way to do this.

Thanks


Solution

  • Hide the stack header likes this:

    <OrderStack.Navigator screenOptions={{ headerShown: false }}>
        {/* whatever */}
    </OrderStack.Navigator>
    

    Configure the drawer header to show stack's screen name:

    import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
    
    // ...
    
    <Drawer.Navigator
      initialRouteName="Home"
      screenOptions={({ route }) => {
        const routeName =
          getFocusedRouteNameFromRoute(route) ?? 'OrderSearchScreen';
    
        let headerTitle;
    
        switch (routeName) {
          case 'OrderSearchScreen':
            headerTitle = 'Search';
            break;
          case 'OrderNumberScreen':
            headerTitle = 'Order no.';
            break;
        }
    
        return {
          headerTitle,
          headerShown: true,
          headerStyle: { backgroundColor: '#009387' },
          headerTintColor: '#fff',
          headerTitleStyle: { fontWeight: 'bold' },
          headerTitleAlign: 'center',
        };
      }}
    >
      {/* whatever */}
    </Drawer.Navigator>;
    

    Docs: https://reactnavigation.org/docs/screen-options-resolution/#setting-parent-screen-options-based-on-child-navigators-state

    If you want to show both hamburger menu and back icon, you need to use headerLeft to override the default one. Though it's very unusual to show both at once.