Deep Linking
Implement deep linking to allow users to navigate directly to specific screens in your React Native app. This is a foundational concept in cross-platform mobile development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world React Native experience. Take your time with each section and practice the examples
Deep Link Setup
Configure deep linking for both iOS and Android platforms with proper URL schemes and universal links.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Navigation Handling
Handle deep link navigation and route users to appropriate screens based on URL parameters.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Deep Linking Implementation
// services/deepLinkManager.js
import { Linking } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
class DeepLinkManager {
constructor() {
this.navigationRef = null;
this.initialUrl = null;
this.setupLinking();
}
setNavigationRef(ref) {
this.navigationRef = ref;
}
setupLinking() {
// Handle initial URL when app is opened
Linking.getInitialURL().then(url => {
if (url) {
this.initialUrl = url;
this.handleDeepLink(url);
}
});
// Handle URL when app is already running
Linking.addEventListener('url', ({ url }) => {
this.handleDeepLink(url);
});
}
handleDeepLink(url) {
console.log('Deep link received:', url);
const parsedUrl = this.parseUrl(url);
if (parsedUrl) {
this.navigateToScreen(parsedUrl);
}
}
parseUrl(url) {
try {
const urlObj = new URL(url);
const path = urlObj.pathname;
const params = Object.fromEntries(urlObj.searchParams);
return {
path,
params,
scheme: urlObj.protocol.replace(':', ''),
host: urlObj.host,
};
} catch (error) {
console.error('Error parsing URL:', error);
return null;
}
}
navigateToScreen(parsedUrl) {
if (!this.navigationRef) {
console.log('Navigation ref not ready, storing for later');
return;
}
const { path, params } = parsedUrl;
switch (path) {
case '/profile':
this.navigationRef.navigate('Profile', { userId: params.id });
break;
case '/product':
this.navigationRef.navigate('Product', {
productId: params.id,
category: params.category
});
break;
case '/order':
this.navigationRef.navigate('Order', { orderId: params.id });
break;
case '/search':
this.navigationRef.navigate('Search', { query: params.q });
break;
case '/notification':
this.navigationRef.navigate('Notification', {
type: params.type,
id: params.id
});
break;
default:
console.log('Unknown deep link path:', path);
}
}
// Generate deep links
generateDeepLink(screen, params = {}) {
const baseUrl = 'yourapp://';
const queryString = Object.keys(params)
.map(key => `${key}=${encodeURIComponent(params[key])}`)
.join('&');
return `${baseUrl}${screen}${queryString ? '?' + queryString : ''}`;
}
// Share deep link
async shareDeepLink(screen, params = {}) {
const deepLink = this.generateDeepLink(screen, params);
try {
await Share.share({
message: `Check this out: ${deepLink}`,
url: deepLink,
});
} catch (error) {
console.error('Error sharing deep link:', error);
}
}
}
// Deep link configuration
const linkingConfig = {
prefixes: ['yourapp://', 'https://yourapp.com'],
config: {
screens: {
Home: '',
Profile: 'profile/:userId?',
Product: 'product/:productId',
Order: 'order/:orderId',
Search: 'search',
Notification: 'notification/:type/:id?',
Settings: 'settings',
},
},
};
// Deep link hook
const useDeepLink = () => {
const [deepLinkData, setDeepLinkData] = useState(null);
const deepLinkManager = useRef(new DeepLinkManager());
useEffect(() => {
const handleDeepLink = (url) => {
const parsed = deepLinkManager.current.parseUrl(url);
setDeepLinkData(parsed);
};
const unsubscribe = Linking.addEventListener('url', ({ url }) => {
handleDeepLink(url);
});
return unsubscribe;
}, []);
const generateLink = (screen, params) => {
return deepLinkManager.current.generateDeepLink(screen, params);
};
const shareLink = (screen, params) => {
return deepLinkManager.current.shareDeepLink(screen, params);
};
return {
deepLinkData,
generateLink,
shareLink,
};
};
// Deep link button component
const DeepLinkButton = ({ screen, params, children, ...props }) => {
const { generateLink, shareLink } = useDeepLink();
const handlePress = () => {
const link = generateLink(screen, params);
console.log('Generated deep link:', link);
// You can copy to clipboard or share
};
return (
<TouchableOpacity onPress={handlePress} {...props}>
{children}
</TouchableOpacity>
);
};
// Android configuration
// android/app/src/main/AndroidManifest.xml
const androidManifestConfig = `
<activity
android:name=".MainActivity"
android:exported="true"
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>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="yourapp.com" />
</intent-filter>
</activity>
`;
// iOS configuration
// ios/YourApp/Info.plist
const iosInfoPlistConfig = `
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>yourapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>yourapp</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>yourapp.com</string>
<key>CFBundleURLSchemes</key>
<array>
<string>https</string>
</array>
</dict>
</array>
`;
export { DeepLinkManager, linkingConfig, useDeepLink, DeepLinkButton };