Search code examples
react-nativereact-navigation-stackreact-navigation-v5

React navigation v5, add a stack navigation to my application header


I'm using react navigation 5 to build my app navigation system.

I want to add a link to open Notifications scree:

I created a RenderHeaderRight component to override the right component of all my stacks

navigation :

const RenderHeaderRight = ({navigation}) => {
  return (
    <View style={{flexDirection: 'row-reverse'}}>
      <TouchableHighlight
        underlayColor={COLORS.DEFAULT}
        style={styles.iConMenuContainer}
        onPress={() => navigation.openDrawer()}>
        <Image source={menu} style={styles.iConMenu} />
      </TouchableHighlight>
      <TouchableHighlight
        underlayColor={COLORS.DEFAULT}
        style={styles.notificationsIconContainer}
        onPress={() => navigation.navigate('Notifications')}>
        <>
          <Image source={notifications} style={styles.notificationsIcon} />
          <Image source={notifMark} style={styles.badge} />
        </>
      </TouchableHighlight>
    </View>
  );
};

In my HomeStackScreen i'm using the RenderHeaderRight :

const HomeStackScreen = ({navigation}) => (
  <HomeStack.Navigator
    initialRouteName="Home"
    headerMode="screen"
    mode="modal"
    screenOptions={{
      headerStyle: {
        backgroundColor: COLORS.WHITE,
        elevation: 0, // remove shadow on Android
        shadowOpacity: 0, // remove shadow on iOS
        borderBottomWidth: 0,
      },
      headerTintColor: COLORS.GREY,
      headerTitleStyle: {
        fontFamily: 'Montserrat-SemiBold',
        fontWeight: '600',
        fontSize: 18,
      },
    }}>
    <HomeStack.Screen
      name="Home"
      component={Home}
      options={{
        title: 'Expanded',
        headerLeft: () => <RenderHeaderLeft />,
        headerRight: () => <RenderHeaderRight navigation={navigation} />,
        headerTitleAlign: 'left',
      }}
    />
    <HomeStack.Screen name="HomeDetails" component={HomeDetails} />
  </HomeStack.Navigator>
);

When i click on the Header right button to open the Notifications screen i got an error :

The action 'NAVIGATE' with payload {"name":"Notifications"} was not handled by any navigator.

Where shoud i create the stack navigation of Notifications screen ?

I triend to add the notifications like this :

const HomeStackScreen = ({navigation}) => (
  <HomeStack.Navigator
    initialRouteName="Home"
    headerMode="screen"
    mode="modal"
    screenOptions={{
      headerStyle: {
        backgroundColor: COLORS.WHITE,
        elevation: 0, // remove shadow on Android
        shadowOpacity: 0, // remove shadow on iOS
        borderBottomWidth: 0,
      },
      headerTintColor: COLORS.GREY,
      headerTitleStyle: {
        fontFamily: 'Montserrat-SemiBold',
        fontWeight: '600',
        fontSize: 18,
      },
    }}>
    <HomeStack.Screen
      name="Home"
      component={Home}
      options={{
        title: 'Expanded',
        headerLeft: () => <RenderHeaderLeft />,
        headerRight: () => <RenderHeaderRight navigation={navigation} />,
        headerTitleAlign: 'left',
      }}
    />
    <HomeStack.Screen name="HomeDetails" component={HomeDetails} />
    <HomeStack.Screen
      name="Notifications".   // add the screen here
      component={Notifications}
      options={{headerShown: false}}
    />
  </HomeStack.Navigator>
);

Solution

  • Removed the unnecessary styling / images

    From my understanding you need to have a root Drawer.Navigator and from inside your Home screen, you need a Stack.Navigator there

    This article explains the details of combining react-native-navigators

    import React from "react"
    import { TouchableHighlight, View, Text } from "react-native"
    import { NavigationContainer } from "@react-navigation/native"
    import { createDrawerNavigator } from "@react-navigation/drawer"
    import { createStackNavigator } from "@react-navigation/stack"
    
    const RenderHeaderRight = ({ navigation }) => {
      return (
        <View style={{ flexDirection: "row-reverse" }}>
          <TouchableHighlight onPress={() => navigation.openDrawer()}>
            <View>
              <Text>Menu</Text>
            </View>
          </TouchableHighlight>
          <TouchableHighlight onPress={() => navigation.navigate("Notifications")}>
            <>
              <View>
                <Text>Image 1</Text>
              </View>
              <View>
                <Text>Image 2</Text>
              </View>
            </>
          </TouchableHighlight>
        </View>
      )
    }
    
    const Stack = createStackNavigator()
    const Drawer = createDrawerNavigator()
    
    const Notifications = () => (
      <View>
        <Text>Notifications</Text>
      </View>
    )
    const Home = () => (
      <View>
        <Text>Home</Text>
      </View>
    )
    
    const NotificationsScreen = () => (
      <View>
        <Text>Notifications Screen</Text>
      </View>
    )
    const HomeScreen = () => (
      <View>
        <Stack.Navigator>
          <Stack.Screen
            name="Home"
            component={Home}
            options={({ navigation }) => ({
              title: "Home",
              headerRight: () => <RenderHeaderRight navigation={navigation} />,
            })}
            navigationOptions={({ navigation }) => ({
              headerTitleAlign: "left",
            })}
          />
          <Stack.Screen name="Notifications" component={Notifications} />
        </Stack.Navigator>
      </View>
    )
    
    export default function App() {
      return (
        <NavigationContainer>
          <Drawer.Navigator initialRouteName="Home">
            <Drawer.Screen name="Home" component={HomeScreen} />
            <Drawer.Screen name="Notifications" component={NotificationsScreen} />
          </Drawer.Navigator>
        </NavigationContainer>
      )
    }