Chapter 9: Expo Router Stack Navigation
1. What is Stack Navigation in Expo Router?
Stack Navigation is a navigation pattern that organizes the navigation history in a stack, allowing users to push and pop screens off the stack. It mimics the navigation flow of most mobile apps where users can move forward to a new screen and back to the previous one.
Key Points:
- Stack-Based Navigation: Each new screen is pushed onto a stack.
- Back Button: Users can navigate back to the previous screen.
- History Management: Stack navigation manages the history of screens for easy back-and-forth navigation.
Example Scenario: Navigating from a Home screen to a Details screen and then back to Home.
2. Setting Up Expo Stack Navigator
To use Stack navigation in your Expo project, you’ll use the Stack component from expo-router/stack. Below are the steps to set it up:
Step 1: Install Necessary Dependencies
- Ensure that your Expo project is set up with
expo-router. The Expo Router is included by default in newer Expo projects.
Step 2: Create a File Structure for Navigation
- Use file-based routing with Expo. Each screen is a
.jsor.tsxfile within theapp/directory.
Example File Structure:
app/
├── _layout.js
├── index.js
├── details.js
Step 3: Define the Stack Navigator
- Use the
Stackcomponent fromexpo-router/stackin your_layout.jsfile to set up the stack navigation for your app.
// app/_layout.js
import { Stack } from "expo-router/stack";
export default function Layout() {
return (
<Stack>
<Stack.Screen name="index" options={{ title: "Home" }} />
<Stack.Screen name="details" options={{ title: "Details" }} />
</Stack>
);
}
Step 4: Create Screens
- Define the
HomeandDetailsscreens in their respective files.
// app/index.js
import { Link } from "expo-router";
import { View, Text, Button, StyleSheet } from "react-native";
export default function HomeScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Home Screen</Text>
<Link href="/details">
<Button title="Go to Details" />
</Link>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
title: {
fontSize: 24,
marginBottom: 20,
},
});
// app/details.js
import { View, Text, Button, StyleSheet } from "react-native";
import { useRouter } from "expo-router";
export default function DetailsScreen() {
const router = useRouter();
return (
<View style={styles.container}>
<Text style={styles.title}>Details Screen</Text>
<Button title="Go Back" onPress={() => router.back()} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
title: {
fontSize: 24,
marginBottom: 20,
},
});
3. Creating and Navigating Between Screens
Navigating Between Screens:
- Navigation in Expo Router is straightforward. You can use the
Linkcomponent or programmatically navigate usinguseRouter.
Example:
- From the Home screen to the Details screen using a button.
// app/index.js (continued)
<Link href="/details">
<Button title="Go to Details" />
</Link>
- Programmatic navigation using
useRouter.
// app/index.js (alternative)
import { useRouter } from "expo-router";
export default function HomeScreen() {
const router = useRouter();
return (
<View style={styles.container}>
<Text style={styles.title}>Home Screen</Text>
<Button title="Go to Details" onPress={() => router.push("/details")} />
</View>
);
}
4. Handling Navigation State
Handling navigation state in a stack navigator is crucial for managing the app's flow. Expo Router's Stack component provides access to navigation state through various hooks and props.
Common Tasks:
- Detecting Screen Focus: Using
useFocusEffectto trigger actions when a screen gains focus. - Accessing Navigation Parameters: Using
useSearchParamsto retrieve parameters passed between screens.
Example: Detecting Screen Focus
import { useFocusEffect } from "expo-router";
import { useCallback } from "react";
import { View, Text } from "react-native";
export default function DetailsScreen() {
useFocusEffect(
useCallback(() => {
console.log("Screen is focused");
return () => console.log("Screen is unfocused");
}, [])
);
return (
<View>
<Text>Details Screen</Text>
</View>
);
}
Example: Accessing Navigation Parameters
import { useSearchParams } from "expo-router";
export default function DetailsScreen() {
const { itemId } = useSearchParams();
return (
<View>
<Text>Details Screen for Item ID: {itemId}</Text>
</View>
);
}
5. Customizing Stack Navigation with All Different ScreenOptions
You can customize the look and feel of your stack navigator using the ScreenOptions prop. This allows you to set properties like header styles, gestures, animations, etc.
Common ScreenOptions:
- headerStyle: Customizes the header's background color.
- headerTintColor: Changes the color of the header text and icons.
- headerTitleStyle: Adjusts the font size, weight, and alignment of the header title.
- gestureEnabled: Enables or disables gestures like swiping back.
Example: Customizing Screen Options
// app/_layout.js
import { Stack } from "expo-router/stack";
export default function Layout() {
return (
<Stack>
<Stack.Screen
name="index"
options={{
title: "Home",
headerStyle: { backgroundColor: "#f4511e" },
headerTintColor: "#fff",
headerTitleStyle: { fontWeight: "bold" },
}}
/>
<Stack.Screen
name="details"
options={{
title: "Details",
gestureEnabled: true,
headerBackTitle: "Back to Home",
}}
/>
</Stack>
);
}
Example: Animations and Gestures
// app/_layout.js
<Stack.Screen
name="details"
options={{
animationEnabled: true,
gestureEnabled: true,
headerStyle: {
backgroundColor: "blue",
},
headerTintColor: "white",
}}
/>
This chapter provides a comprehensive guide to setting up and using Stack Navigation with Expo Router. By following these examples and understanding the underlying concepts, you'll be able to implement efficient and user-friendly navigation in your React Native Expo applications.