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
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)