React Native Deep Linking
A deep link is a web-style address that opens a specific screen inside an app. A friend shares a product link, a user taps it in a message, and the app opens directly on that product page. Notification taps, email buttons, and marketing campaigns all rely on deep links to drop people exactly where they need to go.
The Normal Path Versus a Deep Link
Without deep link With deep link ───────────────────── ─────────────────────────────── Open app Tap: myapp://product/42 Find Shop tab │ Search for item ▼ Open product 42 App opens on Product 42 directly
Two Kinds of Links
Type Example Behavior ────────────────────────────────────────────────────────────────── Custom scheme myapp://product/42 Opens app if installed Universal / App https://example.com/product/42 Opens app if installed, Link opens website otherwise
Custom schemes are simple to set up and ideal for testing. Universal links on iOS and App Links on Android use normal web addresses, which look professional and fall back to a website when the app is missing.
Step 1: Register a Scheme
Choose a unique scheme name in app.json.
{
"expo": {
"scheme": "myapp"
}
}
Step 2: Map Links to Screens
React Navigation reads a linking configuration that connects address paths to screen names.
import { NavigationContainer } from '@react-navigation/native';
import * as Linking from 'expo-linking';
const prefix = Linking.createURL('/');
const linking = {
prefixes: [prefix, 'https://example.com'],
config: {
screens: {
Home: 'home',
Product: 'product/:id',
Profile: 'user/:username',
Settings: 'settings',
},
},
};
export default function App() {
return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
{/* navigators */}
</NavigationContainer>
);
}
myapp://product/42
│ │
│ └── :id = 42 → passed to the screen as a param
└───────── "product" → Product screen
Step 3: Read the Parameter
function ProductScreen({ route }) {
const { id } = route.params;
return <Text>Showing product {id}</Text>;
}
Treat every incoming value as untrusted text. Validate the id before using it in a request, since anyone can craft a link.
Nested Navigators
Describe the full path through tabs and stacks.
config: {
screens: {
MainTabs: {
screens: {
HomeTab: 'home',
ShopTab: {
screens: {
Product: 'product/:id',
},
},
},
},
},
}
Test Links During Development
Fire a link from the terminal while an emulator runs.
npx uri-scheme open "myapp://product/42" --android
npx uri-scheme open "myapp://product/42" --ios
Handle Links Manually
Read the launching link or listen for links that arrive while the app runs.
import * as Linking from 'expo-linking';
useEffect(() => {
Linking.getInitialURL().then((url) => {
if (url) console.log('Launched with', url);
});
const sub = Linking.addEventListener('url', ({ url }) => {
const parsed = Linking.parse(url);
console.log(parsed.path, parsed.queryParams);
});
return () => sub.remove();
}, []);
Universal Links and App Links
A web address opens the app only when your website proves that you own both. Publish a small verification file on your domain.
iOS https://example.com/.well-known/apple-app-site-association Android https://example.com/.well-known/assetlinks.json
Add matching entries to the app configuration: associated domains for iOS and intent filters for Android. The verification files list the app identifiers that may open your links.
Links from Notifications
A push notification can carry a link in its data. When the user taps it, the app opens the matching screen.
{
"title": "Order shipped",
"body": "Track your package",
"data": { "url": "myapp://orders/981" }
}
Sharing a Link
import { Share } from 'react-native';
Share.share({
message: 'Check out this item: https://example.com/product/42',
});
Safety Checklist
- Validate and sanitize every parameter
- Require sign-in before showing private screens, then continue to the target after login
- Avoid performing actions such as purchases directly from a link
- Provide a graceful screen for unknown or broken paths
Summary
Deep links open exact screens from outside the app. Register a scheme, map paths to screens in the navigation linking configuration, and read parameters from the route. Use custom schemes for testing and universal or app links for production sharing, and validate every incoming value.
