Peter J
Peter J

Reputation: 147

React Native tab navigator nested in stack navigator

I'm relatively new to React Native and am struggling with screens. I've gone through the nested navigation documentation (https://reactnavigation.org/docs/nesting-navigators/) which helped me setup the initial nav setup i have, but im having some issues.

I'm attempting to setup the app so it has the initial screen as a "Select User" which has no tab navigation. After selecting the user, you are redirected to a another screen which has tab navigation. I currently have it working however I am unable to access any route/props/params after the initial screen.

I've had to manually import navigation with import { useNavigation } from "@react-navigation/native"; and even though I'm providing params in the Navigation.push, trying to access {route} in my screens states that route is undefined.

My setup of the screens looks similar to below:

const Tab = createBottomTabNavigator();
const WelcomeStack = createStackNavigator();
const HomeStack = createStackNavigator();
const SettingsStack = createStackNavigator();
const Stack = createStackNavigator();

const WelcomeStackScreen = () => (
    <WelcomeStack.Navigator>
        <WelcomeStack.Screen
            name="Welcome"
            component={WelcomeScreen}
            options={{ headerShown: false }}
        />
        <WelcomeStack.Screen
            name="SignUp"
            component={SignUpScreen}
            options={{ headerShown: false }}
        />
    </WelcomeStack.Navigator>
);

const HomeStackScreen = () => {
    return (
        <HomeStack.Navigator>
            <HomeStack.Screen name="Home" component={HomeScreen} />
            <HomeStack.Screen
                name="Search"
                component={SearchResultScreen}
                options={({ navigation }) => ({
                    headerLeft: () => (
                        <Ionicons
                            name={"arrow-back"}
                            size={30}
                            color={colours.text}
                            style={{ paddingLeft: 15 }}
                            onPress={() => {
                                navigation.goBack();
                            }}
                        />
                    ),
                })}
            />
            <HomeStack.Screen
                name="Select"
                component={SelectScreen}
                options={({ navigation, route }) => ({
                    title: route.params.name,
                    headerLeft: () => (
                        <Ionicons
                            name={"arrow-back"}
                            size={30}
                            color={colours.text}
                            style={{ paddingLeft: 15 }}
                            onPress={() => {
                                navigation.goBack();
                            }}
                        />
                    ),
                })}
            />
            <HomeStack.Screen name="Read" component={ReaderScreen} />
        </HomeStack.Navigator>
    );
};

function SettingsScreen() {
    return (
        <View
            style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
        >
            <Text>TBD</Text>
        </View>
    );
}

const SettingsStackScreen = () => (
    <SettingsStack.Navigator>
        <SettingsStack.Screen name="Settings" component={SettingsScreen} />
    </SettingsStack.Navigator>
);

const TabNavigator = ({ route }) => (
    <Tab.Navigator
        screenOptions={({ route }) => ({
            tabBarIcon: ({ focused, color, size }) => {
                let iconName;
                switch (route.name) {
                    case "Home":
                        iconName = focused ? "home" : "home-outline";
                        break;
                    case "Settings":
                        iconName = focused ? "list" : "list-outline";
                        break;
                    default:
                        break;
                }

                return <Ionicons name={iconName} size={size} color={color} />;
            },
        })}
        tabBarOptions={{
            activeTintColor: "tomato",
            inactiveTintColor: "gray",
        }}
    >
        <Tab.Screen name="Home" component={HomeStackScreen} />
        <Tab.Screen name="Settings" component={SettingsScreen}/>
    </Tab.Navigator>
);

export default function App() {
    return (
        <NavigationContainer theme={navThemeOverride}>
            <Stack.Navigator>
                <Stack.Screen name="Welcome" component={WelcomeStackScreen} />
                <Stack.Screen
                    name="TabNavigator"
                    component={TabNavigator}
                    options={{ headerShown: false }}
                    navigationOptions={{ gesturesEnabled: false }}
                />
            </Stack.Navigator>
        </NavigationContainer>
    );
}

Below is a snippet from the Welcome screen navigation

navigation.push("TabNavigator", {
    screen: "Home",
    params: {
      userId: userId,
  },
});

Upvotes: 3

Views: 5411

Answers (1)

Hend El-Sahli
Hend El-Sahli

Reputation: 6732

Your Home screen you're trying to navigate to from your parent-tab-navigator ... is also a StackNavigator ... and you wanna navigate to Select screen I guess ... so there's an extra level needed for your navigation to work...

   navigation.navigate('TabNavigator', {
      screen: 'Home', // <--- StackNavigator
      params: {
        screen: 'Select', // <-- nested inside HomeStack
        params: {
          title: 'Your custom title for Select screen here ...',
        },
      },
    });

Plus +

There's a double definition for route in your Tab navigator

const TabNavigator = ({ route }) => ( //<--- here
    <Tab.Navigator
        screenOptions={({ route }) => ({ // <- and here

Instead

function TabNavigator() {
  return <Tab.Navigator screenOptions={({ route }) => ({})>{/* ...Tabs... */}</Tab.Navigator>;
}

Upvotes: 3

Related Questions