Skip to main content
Most mobile apps have multiple screens. Navigation is how users move between these screens. React Native doesn’t include built-in navigation - instead, you use a library like React Navigation.

React Navigation

React Navigation is the most popular navigation library for React Native. It provides a JavaScript-based navigation solution that works on both iOS and Android.
React Navigation is not part of React Native core. You need to install it separately:
npm install @react-navigation/native @react-navigation/native-stack
npm install react-native-screens react-native-safe-area-context

Basic Navigation Setup

1

Create a Navigator

import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
2

Create Screen Components

function HomeScreen({navigation}) {
  return (
    <View>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details')}
      />
    </View>
  );
}

function DetailsScreen({navigation}) {
  return (
    <View>
      <Text>Details Screen</Text>
      <Button
        title="Go back"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}
Every screen component receives a navigation prop automatically:
function MyScreen({navigation}) {
  return (
    <View>
      {/* Navigate to another screen */}
      <Button
        title="Go to Profile"
        onPress={() => navigation.navigate('Profile')}
      />

      {/* Go back to previous screen */}
      <Button
        title="Go back"
        onPress={() => navigation.goBack()}
      />

      {/* Go to first screen in stack */}
      <Button
        title="Go to Home"
        onPress={() => navigation.popToTop()}
      />
    </View>
  );
}

Passing Parameters

Pass data between screens:
function HomeScreen({navigation}) {
  return (
    <Button
      title="Go to Profile"
      onPress={() => {
        navigation.navigate('Profile', {
          userId: 123,
          userName: 'John Doe',
        });
      }}
    />
  );
}

Stack Navigator

The most common navigator. Screens stack on top of each other:
import {createNativeStackNavigator} from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          headerStyle: {
            backgroundColor: '#f4511e',
          },
          headerTintColor: '#fff',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        }}
      >
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{title: 'My Home'}}
        />
        <Stack.Screen
          name="Details"
          component={DetailsScreen}
          options={({route}) => ({title: route.params.name})}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Tab Navigator

For bottom tab navigation:
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';

const Tab = createBottomTabNavigator();

function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={({route}) => ({
          tabBarIcon: ({focused, color, size}) => {
            let iconName;

            if (route.name === 'Home') {
              iconName = focused ? 'home' : 'home-outline';
            } else if (route.name === 'Settings') {
              iconName = focused ? 'settings' : 'settings-outline';
            }

            return <Icon name={iconName} size={size} color={color} />;
          },
          tabBarActiveTintColor: 'tomato',
          tabBarInactiveTintColor: 'gray',
        })}
      >
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Drawer Navigator

For side drawer navigation:
import {createDrawerNavigator} from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator
        initialRouteName="Home"
        screenOptions={{
          drawerStyle: {
            backgroundColor: '#c6cbef',
            width: 240,
          },
        }}
      >
        <Drawer.Screen name="Home" component={HomeScreen} />
        <Drawer.Screen name="Profile" component={ProfileScreen} />
        <Drawer.Screen name="Settings" component={SettingsScreen} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

Nested Navigators

Combine different navigator types:
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 HomeTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Feed" component={FeedScreen} />
      <Tab.Screen name="Profile" component={ProfileScreen} />
    </Tab.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={HomeTabs}
          options={{headerShown: false}}
        />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Header Customization

<Stack.Screen
  name="Home"
  component={HomeScreen}
  options={{title: 'My Home'}}
/>
React to navigation events:
import {useEffect} from 'react';
import {useFocusEffect} from '@react-navigation/native';

function ProfileScreen({navigation}) {
  // Runs when screen comes into focus
  useFocusEffect(
    React.useCallback(() => {
      console.log('Screen focused');
      // Fetch fresh data
      fetchUserData();

      return () => {
        console.log('Screen unfocused');
        // Cleanup
      };
    }, [])
  );

  // Alternative: use navigation events
  useEffect(() => {
    const unsubscribe = navigation.addListener('focus', () => {
      console.log('Screen focused');
    });

    return unsubscribe;
  }, [navigation]);

  return <View>{/* Screen content */}</View>;
}

Deep Linking

Handle URLs that open your app:
import {Linking} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';

const linking = {
  prefixes: ['myapp://', 'https://myapp.com'],
  config: {
    screens: {
      Home: 'home',
      Profile: 'profile/:id',
      Settings: 'settings',
    },
  },
};

function App() {
  return (
    <NavigationContainer linking={linking}>
      {/* Your navigators */}
    </NavigationContainer>
  );
}

// Now these URLs work:
// myapp://profile/123
// https://myapp.com/settings

Authentication Flow

Common pattern for login/logout:
import {useState, useEffect} from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    checkLoginStatus();
  }, []);

  const checkLoginStatus = async () => {
    const token = await AsyncStorage.getItem('userToken');
    setIsLoggedIn(!!token);
    setLoading(false);
  };

  if (loading) {
    return <LoadingScreen />;
  }

  return (
    <NavigationContainer>
      <Stack.Navigator>
        {isLoggedIn ? (
          // Logged in screens
          <>
            <Stack.Screen name="Home" component={HomeScreen} />
            <Stack.Screen name="Profile" component={ProfileScreen} />
          </>
        ) : (
          // Auth screens
          <>
            <Stack.Screen name="Login" component={LoginScreen} />
            <Stack.Screen name="Register" component={RegisterScreen} />
          </>
        )}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Programmatic Navigation

Navigate from outside components:
import {createNavigationContainerRef} from '@react-navigation/native';

const navigationRef = createNavigationContainerRef();

function App() {
  return (
    <NavigationContainer ref={navigationRef}>
      {/* navigators */}
    </NavigationContainer>
  );
}

// Navigate from anywhere
export function navigate(name, params) {
  if (navigationRef.isReady()) {
    navigationRef.navigate(name, params);
  }
}

// Usage in non-component files:
import {navigate} from './navigation';

function onPushNotification(data) {
  navigate('Notification', {id: data.notificationId});
}

Best Practices

Define route params with TypeScript to catch errors at compile time.
Don’t pass navigation prop down through multiple components. Use navigation from context instead.
Use useFocusEffect or BackHandler to handle Android’s back button correctly.
Use React.lazy() for screens that aren’t immediately needed.
Don’t refetch data every time user navigates back to a screen.

Common Patterns

<Stack.Navigator>
  <Stack.Group>
    <Stack.Screen name="Home" component={HomeScreen} />
    <Stack.Screen name="Profile" component={ProfileScreen} />
  </Stack.Group>
  <Stack.Group screenOptions={{presentation: 'modal'}}>
    <Stack.Screen name="AddPost" component={AddPostScreen} />
  </Stack.Group>
</Stack.Navigator>

Reset Navigation State

import {CommonActions} from '@react-navigation/native';

function logout(navigation) {
  navigation.dispatch(
    CommonActions.reset({
      index: 0,
      routes: [{name: 'Login'}],
    })
  );
}

Alternative: Native Navigation

For apps requiring native performance, consider:
  • React Native Navigation (Wix): Uses native navigation primitives
  • React Native Screens: Provides native screen optimization

Next Steps

React Navigation Docs

Official React Navigation documentation

Components and APIs

Learn more about React Native components

Build docs developers (and LLMs) love