Home > Net >  React Native Nested Navigation - Shared Component
React Native Nested Navigation - Shared Component

Time:06-02

Using React Navigation 6, is it possible to have two different Navigators navigate to the same route?

In brief, I am trying to have a "shared" component that is (1) loaded upon launch, and (2) can be navigated to after using the back bottom (once you navigate from the "Home" screen) or by clicking a BottomNav Icon.

I have the following in my App.js (extraneous imports removed for clarity). What I am trying to do is have Stack Navigation inside a route (Home.jsx). That route (Home) is also the first route of the BottonNav. I've tried a multitude of ways but either I get the "Require cycles are allowed, but can result in uninitialized values" warning and then the page doesn't load. Or I get errors about nested navigation containers. I did review the code on the react navigation page for nested navigation, but it doesn't appear to address the situation that I am looking to address: Basically sharing a component/route. I could probably just duplicate the code in two different screens but obviously that's not an ideal solution.

Thanks.

import 'react-native-gesture-handler';
import React, {useState} from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();

const HomeStack = () => {
  return (
    <Stack.Navigator initialRouteName="Home">
      <Stack.Screen name="Home" component={Home} options={{ headerShown: false }} />
      <Stack.Screen name="Music" component={Music} options={{ headerShown: false }} />
      <Stack.Screen name="History" component={History} options={{ headerShown: false }} />
      <Stack.Screen name="Tasks" component={Tasks} options={{ headerShown: false }} />
    </Stack.Navigator>

  )
}

const TabNavigator = () => { 
  return(  
        <Tab.Navigator>
        <Tab.Screen name="Home" component={ Home } />
        <Tab.Screen name="Ideas" component={ Ideas } />
        <Tab.Screen name="Calendar" component={ Calendar } />
      </Tab.Navigator>

  )
}


export default function App() {

  return (
    <View style={{paddingTop: StatusBar.currentHeight, flex: 1}}>
    <ThemeProvider theme={ theme }>
    <NavigationContainer>
        <TabNavigator />
    </NavigationContainer>
    </ThemeProvider>
    <ExpoStatusBar style='auto'></ExpoStatusBar>
    </View>
  );
}

CodePudding user response:

You should put the TabNavigator inside the HomeStack and render HomeStack as your primary navigator.

...
const HomeStack = () => {
  return (
    <Stack.Navigator initialRouteName="Tab"> // Make Tab the initialRoute
      <Stack.Screen name="Tab" component={TabNavigator} options={{ headerShown: false }} /> // Include TabNavigator inside HomeStack
      <Stack.Screen name="Music" component={Music} options={{ headerShown: false }} />
      <Stack.Screen name="History" component={History} options={{ headerShown: false }} />
      <Stack.Screen name="Tasks" component={Tasks} options={{ headerShown: false }} />
    </Stack.Navigator>

  )
}
...

export default function App() {

  return (
    <View style={{paddingTop: StatusBar.currentHeight, flex: 1}}>
    <ThemeProvider theme={ theme }>
    <NavigationContainer>
        <HomeStack /> // Render HomeStack instead of TabNavigator
    </NavigationContainer>
    </ThemeProvider>
    <ExpoStatusBar style='auto'></ExpoStatusBar>
    </View>
  );
}
  • Related