Home > Mobile >  How do I handle a combination of stack and page navigation?
How do I handle a combination of stack and page navigation?

Time:10-01

I have a Bottom Tab Navigator that has two tabs. The Home tab contains a FlatList of objects. Once the user clicks on an object they should be routed to a page that contains the item that shouldn't show (as a tab) on the bottom tab, yet should show the bottom tab bar. My solution was to use a stack navigator in combination with a bottom tab navigator (shown below) as described in the official docs. However, when I nest the tab navigator inside of the stack navigator, it doesn't display the tab bar on the stack page. The other way around (stack navigator inside the tab navigator) I get an extra tab with the page, which is also an unwanted result.

I must be missing something. If anyone has a better way to route to an item in a list I'd like to hear it as well.

HomeStack (Stack Navigator) with the page Screen:

import { createStackNavigator } from "@react-navigation/stack";
import { ListItem } from "../components/ListItem/ListItem";

export default function StackNavigator() {
  const Stack = createStackNavigator();
  return (
    <Stack.Navigator
      screenOptions={{ headerShown: false }}
    >
      <Stack.Screen name="ListItem" component={ListItem} />
    </Stack.Navigator>
  );
}

TabsNavigator (BottomTabs) with HomeStack nested in side of it:

import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Home } from "../screens/Home";
import { History } from "../screens/History";
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
import { faList } from "@fortawesome/free-solid-svg-icons/faList";
import { faClockRotateLeft } from "@fortawesome/free-solid-svg-icons/faClockRotateLeft";
import HomeStack from "./HomeStack";

export default function TabsNavigator() {
  const Tab = createBottomTabNavigator();
  return (
    <Tab.Navigator screenOptions={{ headerShown: false }}>
      <Tab.Screen
        name="List"
        component={Home}
        options={{
          tabBarIcon: ({ focused }) => (
            <FontAwesomeIcon
              icon={faList}
              style={{ color: focused ? "#317bc1" : "#CCC" }}
            />
          ),
        }}
      />
      <Tab.Screen
        name="History"
        component={History}
        options={{
          tabBarIcon: ({ focused }) => (
            <FontAwesomeIcon
              icon={faClockRotateLeft}
              style={{ color: focused ? "#317bc1" : "#CCC" }}
            />
          ),
        }}
      />
      <Tab.Screen name="ListItem" component={HomeStack} />
    </Tab.Navigator>
  );
}

App:

import { StyleSheet, View } from "react-native";
import { Provider } from "react-redux";
import configureStore from "./src/redux";
import { NavigationContainer } from "@react-navigation/native";
import Navigator from "./src/routes/TabsNavigator";

export default function App() {
  return (
    <Provider store={configureStore()}>
      <View style={{ flex: 1 }}>
        <NavigationContainer>
          <Navigator />
        </NavigationContainer>
      </View>
    </Provider>
  );
}

CodePudding user response:

Take a reference from this code :

I've just now verified it, fine for me. Go through this code for proper understanding -

import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen(props) {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text onPress={() => props.navigation.navigate('NextScreen')}>Home!</Text>
    </View>
  );
}

function NextScreen(props) {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text  onPress={() => props.navigation.navigate('NextScreen2')}>Next!</Text>
    </View>
  );
}

function NextScreen2(props) {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text onPress={() => props.navigation.navigate('NextScreen3')}>Next2!</Text>
    </View>
  );
}

function NextScreen3(props) {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text onPress={() => props.navigation.navigate('HomeScreen')}>Next3!</Text>
    </View>
  );
}


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

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

const StackNavigator = () => {
  return <stack.Navigator option={{headerShown: false}}>
           <stack.Screen name="HomeScreen" component={HomeScreen}/>
           <stack.Screen name="NextScreen" component={NextScreen}/>
           <stack.Screen name="NextScreen2" component={NextScreen2}/>
           <stack.Screen name="NextScreen3" component={NextScreen3}/>
         </stack.Navigator>
}

function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={StackNavigator} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <MyTabs />
    </NavigationContainer>
  );
}

As per your code change your HomeStack (Stack Navigator) likewise: -

import { createStackNavigator } from "@react-navigation/stack";
import { ListItem } from "../components/ListItem/ListItem";
import { Home } from '...<PATH TO HOME SCREEN>...';
const Stack = createStackNavigator();

export default function StackNavigator() {

  return (
    <Stack.Navigator
      screenOptions={{ headerShown: false }}
    >
      <Stack.Screen name="Home" component={Home} />
      <Stack.Screen name="ListItem" component={ListItem} />
    </Stack.Navigator>
  );
}

Then change your first Tab likewise : -

 <Tab.Screen
        name="List"
        component={HomeStack}
        options={{
          tabBarIcon: ({ focused }) => (
            <FontAwesomeIcon
              icon={faList}
              style={{ color: focused ? "#317bc1" : "#CCC" }}
            />
          ),
        }}
      />
  • Related