Skip to main content

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 &#x27;@react-native-async-storage/async-storage&#x27;;
import { NavigationContainer } from &#x27;@react-navigation/native&#x27;;

const PERSIST_KEY = &#x27;navigation-state&#x27;;

const restoreState = async () => {
  try {
    const state = await Storage.getItem(PERSIST_KEY);
    return state ? JSON.parse(state) : undefined;
  } catch (e) {
    console.error(&#x27;Failed to restore navigation state&#x27;, e);
    return undefined;
  }
};

const saveState = async (state) => {
  try {
    await Storage.setItem(PERSIST_KEY, JSON.stringify(state));
  } catch (e) {
    console.error(&#x27;Failed to save navigation state&#x27;, 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 AsyncStorage or similar for persistent storage
  • Only store navigation state, not user data
  • Handle errors gracefully during restore/save operations
  • Consider using @react-navigation/stack or @react-navigation/tabs specific persistence APIs if available

3. Handling Focus Events

Event Description Usage
focus Triggered when a screen gains focus
import { useFocusEffect } from '@react-navigation/native';

useFocusEffect(
  React.useCallback(() => {
    console.log('Screen focused');
  }, [])
);
blur Triggered when a screen loses focus
useFocusEffect(
  React.useCallback(() => {
    return () => console.log('Screen blurred');
  }, [])
);

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>
  );
}
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');
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.
  • Use useDeepLink to access deep link data
  • Configure scheme in app.json for 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.

Was this article helpful?