Deep Links

A deep link is an external URI that, when clicked, opens a specific scene in your app. After following the configuration instructions, your app is ready to respond to deep link clicks. You create a function inside App.js that receives the incoming deep link and navigates to the relevant scene. You hook this function up to the Linking API of React Native (outside of any component). In our email example, when a user clicks a link like 'email://app?id=12' we navigate them to the 'mail' scene for that id. Follow the testing instructions to check that the deep link behaves as expected.

import {Linking} from 'react-native';

const openLink = (url) => {
  if (url) {
    const id = +url.split('=')[1];
    stateNavigator.navigate('mail', {id});
  }
};
Linking.getInitialURL().then(openLink);
Linking.addEventListener('url', ({url}) => openLink(url));

Priming the Stack

If the user has the app open in the background when they click a deep link, then the new scene is pushed on top of their current stack. In our email example, we can end up with two 'mail' scenes on top of the stack. The user opens the first 'mail' scene inside the app and the second 'mail' scene is pushed on top when they click the deep link. We can fix this by using the Navigation router's fluent navigation to build the exact stack we want. We want to open the mail from the deep link directly on top of the 'inbox' scene.

const openLink = (url) => {
  if (url) {
    const id = +url.split('=')[1];
    const link = stateNavigator.fluent()
      .navigate('inbox')
      .navigate('mail', {id}).url;
    stateNavigator.navigateLink(link);
  }
};

Configuring

Android

Locate the AndroidManifest.xml in the Android project and add the following, replacing the scheme and host strings to match your URI pattern:

<activity
  android:name="com.navigation.reactnative.LinkActivity"
  android:launchMode="singleTask"
  android:exported="true">
    <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="email" android:host="app" />
  </intent-filter>
</activity>

iOS

Open your iOS project in Xcode, select the project in the sidebar and navigate to the Info tab. Scroll down to the 'URL Types' section and add one that matches your URI pattern. In our email example, we'd enter an Identifier of 'email' and a URL Scheme of 'email'.

Locate the AppDelegate.m in the iOS project and add:

#import <React/RCTLinkingManager.h>

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  options:(NSDictionary *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

Testing

Android

Run the following command, changing the link to match your URI pattern and the namespace to match your project:

adb shell am start -W -a android.intent.action.VIEW -d "email://app?id=12" com.email

iOS

Run the following command, changing the link to match your URI pattern:

xcrun simctl openurl booted "email://app?id=12"