Managing Navigation State
1. Using Navigation State
| Property | Description | Usage |
|---|---|---|
| navigation | Provides access to navigation methods and state | const { navigation } = useNavigation(); |
| route | Current route object with params and details | const { route } = useRoute(); |
| navigate | Go to a specific screen by name | navigation.navigate('Profile', { userId: 123 }); |
| goBack | Return to the previous screen in stack | navigation.goBack(); |
| replace | Replace current screen in stack with new one | navigation.replace('Home'); |
Example: Navigation State in Stack Navigator
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Example: Using Route Parameters
function ProfileScreen({ route }) {
const { userId } = route.params;
return (
<View>
<Text>User ID: {userId}</Text>
</View>
);
}
Example: Navigating with Parameters
function HomeScreen({ navigation }) {
const handlePress = () => {
navigation.navigate('Profile', { userId: 123 });
};
return (
<Button title="Go to Profile" onPress={handlePress} />
);
}
2. Persisting Navigation State
Example: Using AsyncStorage to persist navigation state
import * as Storage from '@react-native-async-storage/async-storage';
import { NavigationContainer } from '@react-navigation/native';
const PERSIST_KEY = 'navigation-state';
const restoreState = async () => {
try {
const state = await Storage.getItem(PERSIST_KEY);
return state ? JSON.parse(state) : undefined;
} catch (e) {
console.error('Failed to restore navigation state', e);
return undefined;
}
};
const saveState = async (state) => {
try {
await Storage.setItem(PERSIST_KEY, JSON.stringify(state));
} catch (e) {
console.error('Failed to save navigation state', e);
}
};
// In your App component
<NavigationContainer
initialState={await restoreState()}
onStateChange={(state) => saveState(state)}
>
<AppNavigator />
</NavigationContainer>
| Property | Description | Default | Notes |
|---|---|---|---|
| initialState | Initial navigation state to restore from storage | undefined |
Used for hydration on app start |
| onStateChange | Callback when navigation state changes | undefined |
Used to persist updated state |
Note: Navigation state includes screen stack, tab index, and route params. It's recommended to store only the minimal necessary state for restoration.
Warning: Never persist sensitive user data in navigation state. Navigation state is not encrypted by default.
Best Practices for Navigation State Persistence
- Use
AsyncStorageor similar for persistent storage - Only store navigation state, not user data
- Handle errors gracefully during restore/save operations
- Consider using
@react-navigation/stackor@react-navigation/tabsspecific persistence APIs if available
3. Handling Focus Events
| Event | Description | Usage |
|---|---|---|
| focus | Triggered when a screen gains focus | |
| blur | Triggered when a screen loses focus | |
Example: Managing Focus with Navigation Events
import React from 'react';
import { useFocusEffect } from '@react-navigation/native';
const MyScreen = () => {
useFocusEffect(
React.useCallback(() => {
// Fetch data or start timers when screen is focused
const fetchData = async () => {
const data = await fetch('/api/data');
console.log('Fetched data:', await data.json());
};
fetchData();
return () => {
// Cleanup when screen is blurred
console.log('Cleaning up...');
};
}, [])
);
return <div>My Screen Content</div>;
};
export default MyScreen;
Note:
useFocusEffect is preferred over useEffect for navigation-related side effects because it runs only when the screen is focused, not on every render.4. Accessing Route Parameters
| Parameter | Type | Description |
|---|---|---|
| route | object |
Route object containing route information |
| params | object |
Object containing route parameters |
Example: Accessing Route Parameters
import { useRoute } from '@react-navigation/native';
function UserProfile() {
const route = useRoute();
const { userId, userName } = route.params;
return (
<View>
<Text>User ID: {userId}</Text>
<Text>User Name: {userName}</Text>
</View>
);
}
Note: Route parameters are passed as part of the navigation state and can be accessed using
useRoute hook.
5. Setting Screen Options
| Option | Values | Description |
|---|---|---|
| title | string |
Sets the title of the screen in the header |
| headerTitle | string |
Alternative way to set the title of the screen |
| headerShown | boolean |
Controls whether the header is shown or not |
| headerStyle | object |
Customizes the style of the header (e.g., backgroundColor) |
| headerTintColor | string |
Color of the header title and icons |
| headerBackTitle | string |
Custom title for the back button |
| headerBackTitleVisible | boolean |
Controls whether the back title is visible |
| headerLeft | function |
Custom component for the left side of the header |
| headerRight | function |
Custom component for the right side of the header |
| headerBackImage | function |
Custom back icon image |
| headerBackImageStyle | object |
Style for the back image |
| headerBackground | function |
Custom background component for the header |
| headerBlurEffect | string |
Applies blur effect to the header (e.g., 'light', 'dark') |
| gestureEnabled | boolean |
Enables or disables swipe back gesture |
| freezeOnBlur | boolean |
Freezes screen content when it's not in focus |
Example: Setting Header Title
import { StackScreen } from 'expo-router';\n\n<Stack.Screen \n name="home"\n options={{\n title: 'Home',\n }}\n/>
Example: Hiding Header
import { StackScreen } from 'expo-router';\n\n<Stack.Screen \n name="profile"\n options={{\n headerShown: false,\n }}\n/>
Example: Custom Header Component
import { StackScreen } from 'expo-router';\n\nconst CustomHeader = () => (\n <View style={{ backgroundColor: '#007AFF' }}>\n <Text style={{ color: 'white', fontSize: 18 }}>Custom Header</Text>\n </View>\n);\n\n<Stack.Screen \n name="custom"\n options={{\n headerBackground: CustomHeader,\n }}\n/>
6. Customizing Headers
| Property | Description | Default | Notes |
|---|---|---|---|
| headerTitle | Title of the header | undefined | Overrides screen title |
| headerLeft | Component to render on the left side of header | undefined | Can be used for back button or menu icon |
| headerRight | Component to render on the right side of header | undefined | Can be used for settings or action buttons |
| headerStyle | Style object for the header container | { backgroundColor: '#fff' } | Applies to entire header area |
| headerTitleStyle | Style object for the title text | { fontSize: 18, fontWeight: 'bold' } | Customize font and color |
Example: Custom Header with Icons
import { Header } from 'expo-router';<br><br>export default function CustomHeaderScreen() {<br> return (<br> <Stack.Screen<br> options={{<br> headerTitle: 'My App',<br> headerLeft: () => <Icon name="menu" size={24} />,<br> headerRight: () => <Icon name="settings" size={24} />,<br> headerStyle: { backgroundColor: '#007AFF' },<br> headerTitleStyle: { color: '#fff' }<br> }}<br> /><br> );<br>}
Note: The
headerLeft and headerRight props accept React components, allowing for full customization of header elements.
Warning: When using custom headers, ensure that navigation gestures and back buttons are still functional.
7. Configuring Tab Bar Icons
| Property | Description | Values |
|---|---|---|
| icon | Icon to display in the tab bar | string or ImageSource |
| focusedIcon | Icon to display when tab is focused | string or ImageSource |
| iconStyle | Style to apply to the icon | object or number |
Example: Tab Bar Icon Configuration
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Ionicons
name={focused ? 'home' : 'home-outline'}
size={size}
color={color}
/>
),
}}
/>
</Tab.Navigator>
);
}
Note: Icons must be imported from a compatible icon library such as
@expo/vector-icons.
8. Implementing Authentication Flow
Example: Basic Authentication Flow Setup
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { AuthContext } from './AuthContext';
const Stack = createStackNavigator();
function App() {
return (
<AuthContext.Provider value={authInfo}>
<NavigationContainer>
<Stack.Navigator>
{authInfo.isLoggedIn ? (
<Stack.Screen name="Home" component={HomeScreen} />
) : (
<Stack.Screen name="Login" component={LoginScreen} />
)}
</Stack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
);
}
| Property | Description | Usage |
|---|---|---|
| authInfo.isLoggedIn | Boolean indicating if user is authenticated | Used to conditionally render screens |
| authInfo.user | User object with session data | Provides access to user details in protected screens |
| authInfo.login | Function to authenticate user | Handles login logic and updates auth state |
| authInfo.logout | Function to clear authentication state | Logs out user and navigates to login screen |
Note: Ensure that sensitive data is not exposed in navigation state or logs.
Example: Login Screen with Navigation
import { useContext } from 'react';
import { AuthContext } from './AuthContext';
function LoginScreen({ navigation }) {
const { login } = useContext(AuthContext);
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async () => {
try {
await login(username, password);
navigation.navigate('Home');
} catch (error) {
console.error('Login failed', error);
}
};
return (
<View>
<TextInput
value={username}
onChangeText={setUsername}
placeholder="Username"
/>
<TextInput
value={password}
onChangeText={setPassword}
placeholder="Password"
secureTextEntry
/>
<Button title="Login" onPress={handleLogin} />
</View>
);
}
Example: Protected Home Screen
import { useContext } from 'react';
import { AuthContext } from './AuthContext';
function HomeScreen() {
const { user, logout } = useContext(AuthContext);
return (
<View>
<Text>Welcome, {user.name}!</Text>
<Button title="Logout" onPress={logout} />
</View>
);
}
9. Handling Deep Link Navigation
| Property | Description | Example |
|---|---|---|
| useDeepLink | Hook to handle deep links in Expo apps | const { pathname } = useDeepLink(); |
| handleDeepLink | Function to process deep links | handleDeepLink('exp://myapp/home'); |
Example: Handling Deep Links
import { useDeepLink } from 'expo';\n\nconst handleDeepLink = () => {\n const { pathname } = useDeepLink();\n console.log('Deep link path:', pathname);\n};
Note: Deep links must be configured in
app.json under scheme to work correctly.
Deep Link Navigation Summary
- Use
useDeepLinkto access deep link data - Configure
schemeinapp.jsonfor proper handling - Supports both internal and external deep links
10. Using Navigation Ref
Example: Accessing Navigation Ref
import { NavigationContainer } from '@react-navigation/native';
function App() {
const navigationRef = useNavigationContainerRef();
return (
<NavigationContainer
ref={navigationRef}
onStateChange={(state) => {
// Handle state changes
console.log('Navigation state changed:', state);
}}
>
{/* Your screens */}
</NavigationContainer>
);
}
| Property | Description | Usage |
|---|---|---|
| navigationRef | Reference to the navigation container | Used for programmatic navigation and state access |
Note: The
useNavigationContainerRef hook is available in React Navigation v6+.
Warning: Do not use
navigationRef to navigate directly. Use navigation.navigate instead.
11. Resetting Navigation Stack
| Method | Description | Parameters | Notes |
|---|---|---|---|
| reset | Resets the navigation stack to a new set of routes | routes: array of route objects |
Replaces current stack with new routes |
| resetToRoute | Resets navigation stack to a specific route | route: route object |
Clears stack and pushes the new route |
Example: Resetting Navigation Stack
import { reset } from 'expo-router';
const newRoutes = [
{ name: 'Home', params: {} },
{ name: 'Profile', params: { id: '123' } }
];
reset(newRoutes);
Note: The
reset method replaces the entire navigation stack with a new set of routes, effectively clearing the back stack.
12. Preventing Go Back
| Property | Description | Usage |
|---|---|---|
| preventBack | Boolean flag to prevent navigating back in the stack | preventBack: true |
Example: Preventing Navigation Back
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack
screenOptions={{
preventBack: true,
}}
>
<Stack.Screen name="home" />
<Stack.Screen name="details" />
</Stack>
);
}
Note: Setting
preventBack to true disables the back button in the navigation stack for the current screen.