Handling Deep Links with React Navigation

Author

Spencer Carli

Developer, cat dad, and devout pizza lover. Teaching at React Native School and building apps with Handlebar Labs.

Once you've configured deep linking in your app, which you can learn how to do here (Expo, React Native CLI), what happens once the app opens?

In this lesson we'll configure an app to automatically navigate to the right screen based on the deep linking url.

The app we're starting with grabs a list of people from the Star Wars API and displays their details on a details screen.

Basic App Demo

You can clone this starter project on Github.

We want to set up our app so that it will automatically open up to a detail screen and get the relevant data.

To accomplish that we'll need to do a few things

  1. Enable deep linking in the app (Done)
  2. Configure deep linking in React Navigation
  3. Request person information from data passed in our deep link

Configuring Deep Linking in React Navigation

First, we need to define a path for each of the navigators in the tree. By that I mean that, since we want to set up deep linking to the Details screen we'll also need to set up a path for its parent navigator listing MainApp.

App/index.js

// ...

const MainApp = createStackNavigator({
  List: {
    screen: List,
    navigationOptions: {
      headerTitle: 'People',
    },
    path: 'list',
  },
  Details: {
    screen: Details,
    navigationOptions: {
      headerTitle: 'Details',
    },
    path: 'details',
  },
});

const App = createSwitchNavigator({
  Initializing,
  MainApp: {
    screen: MainApp,
    path: '',
  },
});

// ...

We're also going to need to be able to pass variables to /details. We can designate that by adding a parameter prefixed by :.

// ...

const MainApp = createStackNavigator({
  List: {
    screen: List,
    navigationOptions: {
      headerTitle: 'People',
    },
    path: 'list',
  },
  Details: {
    screen: Details,
    navigationOptions: {
      headerTitle: 'Details',
    },
    path: 'details/:personId',
  },
});

This will allow us to pass a dynamic value such as /details/3.

Next, we need to tell React Navigation what our uriPrefix. This is whatever you configured within Xcode or AndroidManifest.xml.

If you're using Expo then the prefix is going to be different between development and a published app. Fortunately. Expo makes it easy to build the right uriPrefix.

import { Linking } from 'expo';

// ...

const AppContainer = createAppContainer(App);

export default () => {
  const prefix = Linking.makeUrl('/');
  console.log(prefix);

  // if not using expo then prefix would simply be `swapi://`

  return <AppContainer uriPrefix={prefix} />;
};

// ...

I'm logging prefix so we know what to use when opening the url.

The app should now be configured to accept and handle deep linking. To test it run the following command:

Terminal

# iOS
xcrun simctl openurl booted exp://127.0.0.1:19000/--/details/3

# Android
adb shell am start -W -a android.intent.action.VIEW -d "exp://127.0.0.1:19000/--/details/3"

If you're not using expo, or it's a live app, it would look like:

Terminal

# iOS
xcrun simctl openurl booted swapi://details/3

# Android
adb shell am start -W -a android.intent.action.VIEW -d "swapi://details/3"
Deep Link Demo

Request Person Information from Data Passed in Deep Link

Obviously we don't have any data yet. To fix this we need to grab the person id and make a request. To access the personId we just need to use this.props.navigation.getParam('personId') like we would grab any other param.

First we'll check if a full item is passed. If a full item is not passed then we'll try to grab the personId and make a request.

App/screens/Details

// ...

class DetailsScreen extends React.Component {
  // ...

  componentDidMount() {
    const item = this.props.navigation.getParam('item', {});

    if (Object.keys(item).length === 0) {
      const personId = this.props.navigation.getParam('personId', 1);
      fetch(`https://swapi.co/api/people/${personId}`)
        .then(res => res.json())
        .then(res => {
          const data = [];

          Object.keys(res).forEach(key => {
            data.push({ key, value: `${res[key]}` });
          });

          this.setState({ data });
        });
    } else {
      const data = [];

      Object.keys(item).forEach(key => {
        data.push({ key, value: `${item[key]}` });
      });

      this.setState({ data });
    }
  }

  // ...
}

// ...
Final Demo

And there you have it! That's how you configure and interact with deep links in your React Native app.

You can find the final code on Github.

Have a React Native question? Let me know!

Join the email list to be notified of all new lessons and classes!