I was creating a React Native app with Expo a week ago and I had to do a layout with a bottom tab navigator and implement a stack layout at the same time. Stack navigation essentially puts screens on top of other screens when you navigate to other pages, while tab navigation allows you to have a bottom page to choose between pages.
Here is the demo:
Code:
       ShubhamPatilsd
       / 
        tab-stack-example
      
        ShubhamPatilsd
       / 
        tab-stack-example
      
    
    React Native Tab Stack Example
I'm going to be using React Navigation for this example, as it is the recommended library by Expo to use.
To get started, run (if you use npm)
 install @react-navigation/native
or run
 add @react-navigation/native
``` if you use Yarn to get started.
I prefer `yarn` so I chose that one.
Next, if you're using Expo, run
```expo
 install react-native-screens react-native-safe-area-context
``` to install the required dependencies for the project.
There is additional setup for base React Native projects, like pod linking and those additional dependencies, so check out the full setup guide [here](https://reactnavigation.org/docs/getting-started/).
Next, open up your `App.js` or `App.tsx` and import `NavigationContainer` from the React Navigation Library.
Import it by using
```js
import { NavigationContainer } from "@react-navigation/native";
Then, put that component in the your App() component:
export default function App() {
  return (
    <NavigationContainer>
      {/*It's a surprise tool that'll help us later!*/}
    </NavigationContainer>
  );
}
Now, we need to implement the Stack screen navigator.
We are going to import a function that gives us a navigator we can use to wrap all our screens in.
To install the stack navigator, we need an npm package called @react-navigation/native-stack. (Yes, another package 🙄).
Installation with npm:
npm install @react-navigation/native-stack
Installation with yarn:
yarn add @react-navigation/native-stack
Import it with:
import { createNativeStackNavigator } from "@react-navigation/native-stack";
Then, create the navigator with (keep it out of any components):
const Stack = createNativeStackNavigator();
Then, under our <NavigationContainer> component, we add <Stack.Navigator> as so:
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        {/* TODO: Add screens later */}
      </Stack.Navigator>
    </NavigationContainer>
  );
}
And next, as you guessed, we're going to add screens.
Let's create two screens, Main and Settings. Put:
<Stack.Screen name="Main" component={Main}/>
<Stack.Screen name="Settings" component={Settings} />
under <Stack.Navigator>.
Oh no! You don't have a Main/Settings component? Don't worry, we can make one really quickly.
Outside of any of our other components (you can put it inside but I like it outside), create the Main component with
function Main() {
  return <Text style={styles.container}>I ❤ React Native</Text>;
}
function Settings() {
  return <Text style={styles.container}>You got to the settings page</Text>;
}
The styles are the default template styles we're given when creating an Expo app, but if you need them here they are:
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});
Now, your App.js/App.tsx should look like this:
import { StyleSheet, Text } from "react-native";
import * as React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
const Stack = createNativeStackNavigator();
function Main() {
  return <Text style={styles.container}>I ❤ React Native</Text>;
}
function Settings() {
  return <Text style={styles.container}>You got to the settings page</Text>;
}
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Main" component={Main} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});
Okay, now let's add a tab navigator into the mix. Time for more packages 🥳 📦!
Installation with npm:
npm install @react-navigation/bottom-tabs
Installation with yarn:
yarn add @react-navigation/bottom-tabs
Import it with
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
and add
const Tab = createBottomTabNavigator();
below the Stack definition:
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator(); //this one
Now, let's go to the Main component. You want to change it so that it has a Tab navigator, so that we can have tab-based navigation.
function Main() {
  return (
    <Tab.Navigator
      screenOptions={{
        tabBarActiveTintColor: "#0d9f61",
      }}
    >
      <Tab.Screen
        name="Home"
        component={() => {
          return (
            <View>
              <Text>Home Screen</Text>
            </View>
          );
        }}
        options={{
          headerShown: false,
        }}
      />
      <Tab.Screen
        name="OtherPage"
        component={() => {
          return <Text>Other Screen</Text>;
        }}
        options={{
          headerShown: false,
        }}
      />
    </Tab.Navigator>
  );
}
The Tab.Navigator contains screens that we can navigate to with the bottom tab bar that shows up. 
Here is the code so far:
import { Button, StyleSheet, Text, View } from "react-native";
import * as React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function Main() {
  return (
    <Tab.Navigator
      screenOptions={{
        tabBarActiveTintColor: "#0d9f61",
      }}
    >
      <Tab.Screen
        name="Home"
        component={() => {
          return (
            <View>
              <Text>Home Screen</Text>
            </View>
          );
        }}
        options={{
          headerShown: false,
        }}
      />
      <Tab.Screen
        name="OtherPage"
        component={() => {
          return <Text>Other Screen</Text>;
        }}
        options={{
          headerShown: false,
        }}
      />
    </Tab.Navigator>
  );
}
function Settings() {
  return <Text style={styles.container}>You got to the settings page</Text>;
}
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Main" component={Main} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});
Now, go to the Main function and add a navigator parameter to the function's parameters like so:
function Main({navigation}){
    /*...*/
}
Then, go to the Tab.Screen called "Home", and change it to
 <Tab.Screen
        name="Home"
        component={() => {
          return (
            <View>
              <Text>Home Screen</Text>
              <Button
                onPress={() => {
                  navigation.navigate("Settings");
                }}
                title="Go to settings"
              />
            </View>
          );
        }}
        options={{
          headerShown: false,
        }}
      />
Here, we added a button, so that we can go back to the Settings page. The onPress with navigation.navigate does the action of going to the "Settings" page when pressed.
And there you have it!
Here is the demo:
This is the entire code:
import { Button, StyleSheet, Text, View } from "react-native";
import * as React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function Main({ navigation }) {
  return (
    <Tab.Navigator
      screenOptions={{
        tabBarActiveTintColor: "#0d9f61",
      }}
    >
      <Tab.Screen
        name="Home"
        component={() => {
          return (
            <View>
              <Text>Home Screen</Text>
              <Button
                onPress={() => {
                  navigation.navigate("Settings");
                }}
                title="Go to settings"
              />
            </View>
          );
        }}
        options={{
          headerShown: false,
        }}
      />
      <Tab.Screen
        name="OtherPage"
        component={() => {
          return <Text>Other Screen</Text>;
        }}
        options={{
          headerShown: false,
        }}
      />
    </Tab.Navigator>
  );
}
function Settings() {
  return <Text style={styles.container}>You got to the settings page</Text>;
}
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Main" component={Main} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});
Hope this helps and I'll come back in a couple of weeks with more stuff!
In the mean time, follow me on Twitter to get more frequent updates on my coding journey!
👋
 
 
              

 
    
Top comments (0)