Handling Deep Links with React Navigation
This lesson was originally publish on React Native School. If you're interested in accessing 110+ React Native articles then be sure to visit!
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.
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
- Enable deep linking in the app (Done)
- Configure deep linking in React Navigation
- 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
.
<p class="code-header">App/index.js</p>
// ...
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 :
.
<p class="code-header"></p>
// ...
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
.
<p class="code-header"></p>
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:
<p class="code-header">Terminal</p>
# 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:19004/--/details/3" com.deeplinking
If you're not using expo, or it's a live app, it would look like:
<p class="code-header">Terminal</p>
# iOS
xcrun simctl openurl booted swapi://details/3
# Android
adb shell am start -W -a android.intent.action.VIEW -d "swapi://details/3" com.deeplinking
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.
<p class="code-header">App/screens/Details</p>
// ...
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(`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 });
}
}
// ...
}
// ...
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!