Deep Linking Integration in React Native Application
Deep linking is a pivotal technique in mobile app development. It directs users to specific screens within an app through designated URLs or resources. Deep linking improves user experience by directing them to specific screens, even within complex app structures, rather than just launching the app. It seamlessly guides users to targeted destinations via designated URLs or resources. This functionality holds immense value in diverse domains such as marketing campaigns and user retention strategies. As a common user scenario, encountering deep linking often happens when clicking on a link, like a product in an e-commerce platform, redirecting users directly to the corresponding screen within the app if installed.
In this blog, we’ll look into implementing deep linking within a React Native application. Through an illustrative example, we’ll construct a basic app equipped to handle deep linking and explore the configuration process using the React Navigation library.
Getting Started
To initiate our journey, let’s begin by generating a fresh React Native project:
npx react-native init DeepLinkProject
Moving forward, proceed to install the necessary dependencies for React Navigation:
yarn add @react-navigation/native
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
We'll also need to install the 'react-navigation/stack' package, which serves as our navigation solution:
yarn add @react-navigation/stack
Configuring Deep Linking with React Navigation
For integrating deep linking, we'll leverage React Native's Linking API. Additionally, we'll employ the useEffect hook to manage deep links effectively. Begin by establishing the Stack Navigator within our App.tsx file:
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { Text, View } from 'react-native';
const Stack = createStackNavigator();
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
function ProfileScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Profile Screen</Text>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
We've developed two screens: HomeScreen and ProfileScreen. Now, it's time to integrate deep linking into these screens.
Initially, we'll craft a useEffect hook within the App component to manage deep links. Within this hook, we'll incorporate an event listener to Linking, enabling the parsing of incoming URLs and navigation to the appropriate screen:
import * as React from 'react';
import { Linking } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { Text, View } from 'react-native';
const Stack = createStackNavigator();
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
function ProfileScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Profile Screen</Text>
</View>
);
}
export default function App() {
React.useEffect(() => {
const handleDeepLink = ({ url }: { url: string }) => {
const route = url.replace(/.*?:\/\//g, '');
const routeName = route.split('/')[0];
if (routeName === 'profile') {
const username = route.split('/')[1];
navigation.navigate('Profile', { username });
}
};
Linking.addEventListener('url', handleDeepLink);
return () => {
Linking.removeEventListener('url', handleDeepLink);
};
}, []);
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={({ route }) => ({ title: route.params.username })}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
Within the useEffect hook, we initially define a function named handleDeepLink to manage the incoming deep link. This function extracts the route name along with any parameters from the URL and then navigates to the corresponding screen using navigation.navigate.
Subsequently, in the ProfileScreen component, we can access the username parameter via route.params.username and utilize it to set the screen's title via the options prop.
Folder Structure
MyProject/├─ __tests__/
├─ android/
├─ ios/
├─ src/
│ ├─ screens/
│ │ ├─ HomeScreen.tsx
│ │ ├─ ProfileScreen.tsx
│ ├─ App.tsx
├─ package.json
We'll maintain our React Navigation stack within the App.tsx file, while dedicating separate files for each screen within the screens folder.
Full Code
Below is the complete code for the application.
App.tsx
import * as React from 'react';
import { Linking } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { Text, View } from 'react-native';
import HomeScreen from './screens/HomeScreen';
import ProfileScreen from './screens/ProfileScreen';
const Stack = createStackNavigator();
export default function App() {
React.useEffect(() => {
const handleDeepLink = ({ url }: { url: string }) => {
const route = url.replace(/.*?:\/\//g, '');
const routeName = route.split('/')[0];
if (routeName === 'profile') {
const username = route.split('/')[1];
navigation.navigate('Profile', { username });
}
};
Linking.addEventListener('url', handleDeepLink);
return () => {
Linking.removeEventListener('url', handleDeepLink);
};
}, []);
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={({ route }) => ({ title: route.params.username })}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
screens/HomeScreen.tsx
import * as React from 'react';
import { View, Text, Button } from 'react-native';
interface Props {
navigation: any;
}
export default function HomeScreen({ navigation }: Props) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Profile', { username: 'johndoe' })}
/>
</View>
);
}
screens/ProfileScreen.tsx
import * as React from 'react';
import { View, Text } from 'react-native';
interface Props {
route: any;
}
export default function ProfileScreen({ route }: Props) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Profile Screen</Text>
<Text>{route.params.username}</Text>
</View>
);
}
Conclusion
Within this piece, we've delved into the implementation of deep linking within a React Native application utilizing the React Navigation library. We've thoroughly addressed considerations spanning various platforms and versions, and supplemented our discourse with TypeScript code samples for clarity and applicability across different development environments.
Happy Learning!!