This comparison covers the primary tools for handling navigation, routing, and touch gestures across the React ecosystem. react-router and react-router-dom are the standard choices for web applications, managing URL history and component rendering based on location. react-navigation and react-native-navigation are the leading solutions for React Native mobile apps, handling stack navigation, tabs, and deep linking. react-native-gesture-handler provides native-level touch processing, often powering the interactions within native navigation libraries. Together, these packages define how users move through and interact with React interfaces on different platforms.
Building applications with React means solving two distinct problems: how users move between screens (navigation) and how they interact with elements (gestures). The packages in this comparison split cleanly between web and mobile environments. react-router and react-router-dom handle the browser's address bar and history. react-navigation, react-native-navigation, and react-native-gesture-handler handle mobile stacks, tabs, and touch physics. Let's look at how they solve these problems differently.
Every app needs a top-level wrapper to manage state. On the web, this wraps the browser history. On mobile, it wraps the native navigation container.
react-router-dom uses a router component to wrap your app.
// react-router-dom: Web setup
import { BrowserRouter } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>...</Routes>
</BrowserRouter>
);
}
react-router is the core logic package.
BrowserRouter.// react-router: Core hooks usage
import { useLocation } from 'react-router';
function Debug() {
const location = useLocation();
return <div>{location.pathname}</div>;
}
react-navigation uses a container for mobile stacks.
// react-navigation: Mobile setup
import { NavigationContainer } from '@react-navigation/native';
function App() {
return (
<NavigationContainer>
<Stack.Navigator>...</Stack.Navigator>
</NavigationContainer>
);
}
react-native-navigation uses a static API to set roots.
// react-native-navigation: Native setup
import { Navigation } from 'react-native-navigation';
Navigation.setRoot({
root: {
stack: {
children: [{ component: { name: 'Home' } }]
}
}
});
react-native-gesture-handler requires a root view wrapper.
// react-native-gesture-handler: Gesture setup
import { GestureHandlerRootView } from 'react-native-gesture-handler';
function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<NavigationContainer>...</NavigationContainer>
</GestureHandlerRootView>
);
}
How you map URLs or screen names to components varies by platform philosophy.
react-router-dom uses declarative route components.
<Route> elements inside <Routes>.// react-router-dom: Route definition
<Routes>
<Route path="/users/:id" element={<UserProfile />} />
</Routes>
react-router provides the matching logic.
react-router-dom.// react-router: Match logic (simplified)
// Typically used via hooks like useMatch in custom implementations
import { useMatch } from 'react-router';
const match = useMatch('/users/:id');
react-navigation uses a navigator component configuration.
// react-navigation: Stack definition
<Stack.Navigator>
<Stack.Screen name="UserProfile" component={UserProfile} />
</Stack.Navigator>
react-native-navigation registers components globally.
// react-native-navigation: Registration
Navigation.registerComponent('UserProfile', () => UserProfile);
// Usage in setRoot
children: [{ component: { name: 'UserProfile' } }]
react-native-gesture-handler does not define routes.
// react-native-gesture-handler: Interactive area
<PanGestureHandler onGestureEvent={onPan}>
<View><Text>Swipe Me</Text></View>
</PanGestureHandler>
Moving from one view to another is the core job of navigation libraries.
react-router-dom uses a hook or component for navigation.
useNavigate allows programmatic changes.<Link> creates anchor tags.// react-router-dom: Programmatic nav
import { useNavigate } from 'react-router-dom';
function Button() {
const navigate = useNavigate();
return <button onClick={() => navigate('/home')} />;
}
react-router exposes the history interface.
// react-router: History interface
import { useNavigate } from 'react-router';
// Same hook, but core logic is platform independent
react-navigation uses a navigation prop or hook.
navigation.navigate pushes to the stack.// react-navigation: Programmatic nav
import { useNavigation } from '@react-navigation/native';
function Button() {
const navigation = useNavigation();
return <button onPress={() => navigation.navigate('Home')} />;
}
react-native-navigation uses static navigation commands.
Navigation.push takes a component ID and props.// react-native-navigation: Programmatic nav
import { Navigation } from 'react-native-navigation';
Navigation.push('componentId', {
component: { name: 'Home' }
});
react-native-gesture-handler triggers actions via gestures.
// react-native-gesture-handler: Gesture action
onEnded={() => {
if (translationX < -100) navigation.goBack();
}}
Mobile apps rely heavily on touch gestures, while web apps rely on clicks and hovers.
react-router-dom handles click events on links.
<a> tags to prevent full page reloads.// react-router-dom: Link interaction
<Link to="/settings">Settings</Link>
// Renders an <a> tag that uses JS navigation
react-router has no interaction components.
// react-router: State check
// No direct interaction components
react-navigation includes basic gesture support.
react-native-gesture-handler.// react-navigation: Default gesture
// Enabled via screenOptions
<Stack.Screen options={{ gestureEnabled: true }} />
react-native-navigation uses native touch drivers.
react-navigation.// react-native-navigation: Native gesture
// Configured via native options object
options: {
gestures: {
enabled: true
}
}
react-native-gesture-handler provides granular touch control.
// react-native-gesture-handler: Custom tap
<TapGestureHandler numberOfTaps={2} onActivated={onDoubleTap}>
<View><Text>Double Tap</Text></View>
</TapGestureHandler>
Despite the platform split, these libraries share core React concepts.
react-native-navigation static API) use React components to define structure.// Shared pattern: Provider wrapping
// Web
<BrowserRouter>...</BrowserRouter>
// Native
<NavigationContainer>...</NavigationContainer>
// Web
<Route path="/" element={<Home />} />
// Native
<Stack.Screen name="Home" component={Home} />
// Web
const { pathname } = useLocation();
// Native
const navigation = useNavigation();
// Web
const About = lazy(() => import('./About'));
// Native
// Supported via getComponent in screen options
// Web
// Handled by browser URL bar
// Native
// Configured via linking prop in NavigationContainer
| Feature | react-router-dom | react-navigation | react-native-navigation |
|---|---|---|---|
| Platform | 🌐 Web Browser | 📱 React Native | 📱 React Native |
| Routing Style | URL-based | Name-based (JS) | Name-based (Native) |
| Performance | JS-driven | JS-driven + Native | Fully Native |
| Setup | Component Wrapper | Component Wrapper | Static API |
| Gestures | Click/Hover only | JS + Gesture Handler | Native Drivers |
react-router-dom is the standard for web. If you are building a website, this is your starting point. It integrates perfectly with browser history and SEO requirements.
react-navigation is the standard for React Native. It offers the best balance of ease-of-use and power. It feels like React, which makes it easy for web developers to transition to mobile.
react-native-navigation is for teams that need maximum native performance. It is stricter and requires more native knowledge, but it delivers the most "native" feel.
react-native-gesture-handler is a utility for mobile. You will likely use it alongside react-navigation to unlock advanced touch features that the default system cannot handle.
react-router is the engine under the hood for web routing. You rarely install it alone, but understanding it helps when debugging complex routing logic.
Final Thought: Do not try to force web patterns onto mobile or vice versa. Respect the platform. Use react-router-dom for the browser and react-navigation for mobile apps to ensure your users get the experience they expect on their device.
Choose react-native-gesture-handler when building React Native apps that require complex touch interactions like swipe-to-delete, pinch-to-zoom, or custom gesture recognizers. It is often a required peer dependency for react-navigation to enable smooth gesture-based navigation transitions. Use it when the default React Native touch system feels too slow or lacks the precision needed for high-fidelity interactions.
Choose react-native-navigation if you need fully native navigation stacks with true native performance and look-and-feel on iOS and Android. It is ideal for apps that prioritize native platform conventions over JavaScript flexibility. Be aware that it requires more native code configuration and differs significantly from standard React web patterns.
Choose react-navigation for most React Native projects because it offers a balanced mix of JavaScript flexibility and native performance. It has a massive ecosystem of plugins, supports deep linking out of the box, and mimics web-like routing patterns that many developers find familiar. It is the community standard and integrates seamlessly with react-native-gesture-handler.
Choose react-router as the core dependency if you are building a routing system for a non-DOM environment (like React Native) using the web logic, or if you need low-level routing primitives. For standard web development, you will typically install react-router-dom which includes this package. Use the core package directly only if you are building a custom router adapter for a specific platform.
Choose react-router-dom for virtually all standard React web applications running in a browser. It provides the essential components like BrowserRouter, Link, and Routes that interact with the browser's history API. It is the go-to solution for managing URL state, nested routes, and lazy loading in web projects.
React Native Gesture Handler provides native-driven gesture management APIs for building best possible touch-based experiences in React Native.
With this library gestures are no longer controlled by the JS responder system, but instead are recognized and tracked in the UI thread. It makes touch interactions and gesture tracking not only smooth, but also dependable and deterministic.
Check getting started section of our docs for the detailed installation instructions.
Check out our dedicated documentation page for info about this library, API reference and more: https://docs.swmansion.com/react-native-gesture-handler/docs/
If you want to play with the API but don't feel like trying it on a real app, you can run the example project. Clone the repo, go to the example folder and run:
yarn install
Run yarn start to start the metro bundler
Run yarn android or yarn ios (depending on which platform you want to run the example app on).
You will need to have an Android or iOS device or emulator connected.
react-native-gesture-handler supports the three latest minor releases of react-native.
| version | react-native version |
|---|---|
| 2.28.0+ | 0.79.0+ |
| 2.26.0+ | 0.78.0+ |
| 2.25.0+ | 0.76.0+ |
| 2.24.0+ | 0.75.0+ |
| 2.21.0+ | 0.74.0+ |
| 2.18.0+ | 0.73.0+ |
| 2.16.0+ | 0.68.0+ |
| 2.14.0+ | 0.67.0+ |
| 2.10.0+ | 0.64.0+ |
| 2.0.0+ | 0.63.0+ |
It may be possible to use newer versions of react-native-gesture-handler on React Native with version <= 0.59 by reverse Jetifying. Read more on that here https://github.com/mikehardy/jetifier#to-reverse-jetify--convert-node_modules-dependencies-to-support-libraries
Gesture handler library is licensed under The MIT License.
This project has been build and is maintained thanks to the support from Shopify, Expo.io and Software Mansion
Join the Software Mansion Community Discord to chat about Gesture Handler or other Software Mansion libraries.
Since 2012 Software Mansion is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product – Hire us.