Getting Started with Navigation in React Native
Setting up screen navigation in a React Native app
Almost every React Native app needs more than one screen, and moving between those screens is one of the first real challenges beginners run into. Unlike the web, there's no browser history or URL bar to fall back on — you need a dedicated navigation library.
In this guide, we'll set up React Navigation, the most widely used navigation library in the React Native ecosystem, and build a simple stack of screens that pass data between each other.
Why navigation needs a library
React Native doesn't ship with built-in navigation. Each platform handles screen transitions differently under the hood — iOS and Android have their own native navigation patterns — and React Navigation abstracts both behind a single, consistent API.
Think of a navigator as a stack of cards: pushing a new screen adds a card on top, and going back pops it off.
Installing React Navigation
Start by installing the core package along with the native stack navigator and its required dependencies:
npm install @react-navigation/native @react-navigation/native-stack
npm install react-native-screens react-native-safe-area-context
If you're using Expo, also run npx expo install react-native-screens react-native-safe-area-context so the native modules are linked correctly for your setup.
Setting up a stack navigator
Wrap your app in a NavigationContainer and define a stack with your screens:
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Each Stack.Screen maps a route name to a component. Navigating between them is just a matter of calling navigation.navigate('ScreenName') from inside any screen.
Adding a header title
You can customize each screen's header by passing an options prop to Stack.Screen, for example options={ '{{ title: "My Home" }}' }, or configure shared defaults on the navigator itself.
Passing parameters between screens
Most apps need to send data along when navigating — like an item ID from a list screen to a detail screen:
// From HomeScreen
navigation.navigate('Details', { itemId: 42 });
// Inside DetailsScreen
function DetailsScreen({ route }) {
const { itemId } = route.params;
return <Text>Item ID: {itemId}</Text>;
}
Common mistakes to avoid
- Forgetting to wrap the app in a single
NavigationContainerat the root - Nesting navigators without a clear reason, making the navigation tree hard to follow
- Storing navigation state in component state instead of letting the library manage it
- Not handling the Android hardware back button separately when needed
Once your stack is set up, adding more screens is straightforward — the pattern stays the same as your app grows. From here, you can explore tab navigators and drawer navigators for more complex app layouts.
