Configure Deep Linking in React Navigation for Android and iOS
Learn how to configure React Navigation to handle incoming URLs and open specific screens on Android and iOS, with setup steps, verification commands, and error‑handling strategies.
23 May 2026, 03:34 UTC

Desired outcome
When a user taps a URL that matches your app’s scheme (e.g., yourapp://product/42) or a universal link (e.g., https://yourapp.com/product/42), the app should launch (or come to the foreground) and navigate directly to the ProductDetails screen with the productId parameter set to 42. If the URL does not match any defined pattern, the app should fall back to a generic screen instead of crashing or staying on the current route.
Prerequisites
- React Native project with
@react-navigation/nativeand@react-navigation/native-stackinstalled (version 5.x or 6.x). - Native development tools: Android Studio for Android, Xcode for iOS.
- Basic understanding of React Navigation stack structure and how to define route names and params.
Focused procedure
1. Define the linking configuration
Create a JavaScript object that maps URL patterns to route names and extracts parameters. Place this file (e.g., linking.js) in your project root.
import { Linking } from 'react-native';
const linking = {
prefixes: ['yourapp://', 'https://yourapp.com'],
config: {
screens: {
ProductDetails: 'product/:productId',
Home: '',
},
},
// Optional: retrieve the initial URL on cold start
async getInitialState() {
const url = await Linking.getInitialURL();
if (url) {
return linking.__getInitialState__(url);
}
return undefined;
},
// Optional: handle errors
onError(error) {
console.warn('Deep linking error:', error);
},
};
export default linking;
2. Pass the linking prop to NavigationContainer
In your app’s entry file (usually App.js or index.js), import the linking object and provide it to NavigationContainer.
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import linking from './linking';
function HomeScreen() { /* … */ }
function ProductDetailsScreen({ route }) {
const { productId } = route.params;
// use productId
return /* … */;
}
const Stack = createNativeStackNavigator();
export default function App() {
return (
Loading…}>
);
}
3. Android setup – intent filter
Open android/app/src/main/AndroidManifest.xml and add an intent filter to the MainActivity (or the activity that handles the launch). Replace placeholders with your values.
<activity android:name=".MainActivity" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourapp" />
</intent-filter>
</activity>
If you also want to support HTTPS URLs, add another <data> line with android:host="yourapp.com" and android:scheme="https".
4. iOS setup – Universal Links (or custom scheme)
For a custom URL scheme, open Info.plist and add:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>yourapp</string>
</array>
</dict>
</array>
For Universal Links, you must also:
- Enable the “Associated Domains” capability in Xcode and add
applinks:yourapp.com. - Host an
apple-app-site-associationfile athttps://yourapp.com/apple-app-site-associationwith content similar to:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.yourapp",
"paths": [ "/product/*" ]
}
]
}
}
5. Test the configuration
Use the following commands to verify that deep links work. Replace placeholders with your actual values.
Android
# Assuming you have ADB set up and the app is installed
adb shell am start -W -a android.intent.action.VIEW -d "yourapp://product/42"
Expected result: the app opens (or comes to foreground) and the ProductDetails screen is shown with route.params.productId === '42'.
iOS (simulator or device)
# Open Safari and paste the URL
xcrun simctl openurl booted "https://yourapp.com/product/42"
Expected result: the app launches and navigates to the ProductDetails screen.
Cold launch test
Kill the app completely (swipe away from recent apps or use adb shell am force-stop / terminate in Xcode), then invoke the link again. The initial route should be the linked screen, not the default home screen.
Expected checks
- The navigation state after a link matches the pattern defined in
linking.config.screens. - Parameters are correctly parsed and available via
route.params. - If the URL does not match any pattern, the
fallbackcomponent (or a screen you specify viaonError) is rendered. - No runtime warnings about “Unable to resolve route” appear in the console.
Recovery options
If a link fails to match:
- Fallback screen: Provide a
fallbackprop toNavigationContainer(e.g., a genericNotFoundscreen). - Error callback: Implement
onErrorin the linking object to log the issue and optionally redirect to a known screen. - Debugging: Temporarily set
prefixesto an array containing only['https://']and verify that the linking configuration is being read by checking the console output ofgetInitialState.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.