Setting Up Declarative Deep Linking with React Navigation
Learn how to configure declarative deep linking in a React Native app, extract URL parameters, test the flow, and understand native registration and testing considerations.
05 Sept 2026, 23:08 UTC

Problem: Opening a Specific Screen from an External URL
An email or push notification may contain a link such as myapp://profile/42?ref=campaign. The app should launch and navigate directly to the profile screen for user 42, passing the referral code. Without deep linking you would need to parse the URL, decide which screen to show, and manually push the route, leading to duplicated and error‑prone code.
Thesis: Declarative Linking Removes Manual Parsing
React Navigation’s linking configuration lets you describe the relationship between URL patterns and navigator routes in a single object. The library parses the URL, matches the route, and supplies the parameters automatically, so you can focus on screen content.
1️⃣ Configure the Linking Object
Place the linking object inside the root NavigationContainer. It maps URL schemes and paths to routes and can handle nested navigators.
// App.js
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import ProfileScreen from './screens/ProfileScreen';
const Stack = createStackNavigator();
const linking = {
prefixes: ['myapp://', 'https://myapp.com'],
config: {
screens: {
Home: 'home',
Profile: {
path: 'profile/:userId',
parse: {
userId: Number,
ref: String,
},
screens: {
Details: 'details',
},
},
},
},
};
// Syntax follows React Navigation 6.x; adjust if you use a different major version.
export default function App() {
return (
<NavigationContainer linking={linking} fallback={Loading...}>\n <Stack.Navigator>\n <Stack.Screen name="Home" component={HomeScreen} />\n <Stack.Screen name="Profile" component={ProfileScreen} />\n </Stack.Navigator>\n </NavigationContainer>\n );
}
- prefixes – URL schemes the app should listen for.
- path – fragment that maps to a route;
:userIdis a parameter. - parse – optional conversion of parameters (e.g.,
Number).
2️⃣ Access Parameters Inside the Screen
React Navigation injects a route prop containing a params object. The values from the deep link appear automatically.
// screens/ProfileScreen.js
import { View, Text } from 'react-native';
export default function ProfileScreen({ route }) {
const { userId, ref } = route.params || {};
return (
<View>\n <Text>Profile of user {userId}</Text>\n {ref && <Text>Referred by {ref}</Text>\n </View>
);
}
3️⃣ Handle App Launch and Runtime Links
React Navigation uses Linking.getInitialURL() for the first launch and Linking.addEventListener('url') for links received while the app is open. When you provide the linking prop, this handling is built‑in, so no extra code is required for typical cases.
4️⃣ Test Deep Links with Jest
Unit tests can mock the Linking module to simulate URL openings.
// __mocks__/Linking.js
export default {
getInitialURL: jest.fn().mockResolvedValue('myapp://profile/42?ref=campaign'),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
};
In a test file:
import { render } from '@testing-library/react-native';
import App from '../App';
test('opens profile screen from deep link', async () => {
const { getByText } = render();
expect(getByText(/Profile of user 42/)).toBeTruthy();
expect(getByText(/Referred by campaign/)).toBeTruthy();
});
Run the test with Jest; a successful assertion confirms that the URL was parsed and the correct screen rendered.
Trade‑offs & Limitations
- Native URL Scheme Registration – Add the scheme to
AndroidManifest.xmlandInfo.plist. If omitted, the app will not open from an external link. - Complex Nested Navigators – Deep nesting can make the
linkingobject hard to read. Keep route names unique and consider flattening the structure when possible. - Parameter Types – The
parsefunction supports simple conversions. For richer data you may need to transform values after the route loads. - Testing Scope – Mocking
Linkingcovers unit logic, but integration tests on real devices are still required to verify OS‑level URL handling.
Actionable Next Steps
- List every route you want to expose via deep links and add it to the
linkingconfig.screensobject. - Register the URL scheme in the native files:
- Android: edit
AndroidManifest.xmland add<intent-filter> <data android:scheme="myapp" /> </intent-filter>inside the activity tag. - iOS: open
Info.plistand addCFBundleURLTypeswith an entry for the scheme.
- Android: edit
- Install the
uri-schemeCLI (e.g.,npm i -g uri-scheme) and test manually:npx uri-scheme open myapp://profile/99?ref=google --android npx uri-scheme open myapp://profile/99?ref=google --ios - Write Jest tests that mock
Linkingfor edge cases such as missing parameters or invalid types. - Include the link tests in your CI pipeline, running them on a simulator or connected device.
With a declarative linking setup you eliminate manual URL parsing, reduce bugs, and keep navigation logic transparent across the codebase. Follow the steps above to get deep links working reliably.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.