How to make react-navigation works with Firebase Dynamic link

Luan Castheloge
3 min readAug 9, 2023

--

Over the past few months, I’ve been talking with some junior React Native developers and realized that the deep linking feature isn’t part of their apps. It seems like a next-level feature.

I’m not going to lie, I’ve also had quite complex implementations in some previous experiences, sometimes with Redux and other times with Context API. Fortunately, we have a pretty easy and smooth way to do it, and that’s what I’m going to show you here.

If you’ve ever built a React Native application, you’ve probably used a navigation library. There are several libraries out there, such as react-navigation and react-native-navigation, among others.

I’ve mostly been using react-navigation over the past three years, and I’m happy about it. So, we’re going to use it here.

Let’s get the concept first

Before we talk about code, I think it’s worth to also explain Firebase Dynamic Link, which is a Firebase tool responsible for generating links and making dynamic redirections through our app or to respective app stores (e.g., when you don’t have the app installed).

In order to have this thing working you need to install and configure the react-native-firebase/app and react-native-firebase/dynamic-links

Starting from the point that you have react-navigation up and running in your application, here is what you need to do.

/* TODO:
[] Configure your firebase dynamic link through your firebase admin panel
[] Define your prefix
[] Define the route redirections inside you applications
[] Configure redirections when the app is runing in background
[] Configure redirections when the app is in close state
*/

After your setup at Firebase is ready (you can check here), let’s move to the code:

const DeepLinkingConfig: LinkingOptions = {
prefixes: ['<https://yourapp.com>'],
config: {},
};

After adding the prefixes, you will need to connect the screens and the respective redirectors

const DeepLinkingConfig: LinkingOptions = {
prefixes: ['<https://yourapp.com>'],
config: {
screens: {
ResetPasswordScreen: 'reset_password'
}
}
};

Now we have a very important part, the Dynamic link subscription. This function will define your listener and how it will handle those URLst.

The first listener works when the app is in the foreground state (visible on the device), you can use the onLink method to subscribe to events as and when they happen:

const DeepLinkingConfig: LinkingOptions = {
prefixes: ['<https://safeby.com.br>'],
config: {
screens: {
ResetPasswordScreen: 'reset_password'
}
},
subscribe(listener) {
const onReceiveURL = ({ url }: { url: string }) => listener(url);
// Listen to incoming links from deep linking
Linking.addEventListener('url', onReceiveURL);

// listen to firebase dynamic link
const unsubscribeForegroundLinkingEvents = dynamicLinks().onLink(link => {
if (link.url) {
listener(link.url);
}
});
return () => {
// Clean up the event listeners
Linking.removeEventListener('url', onReceiveURL);
unsubscribeForegroundLinkingEvents();
};
}
};

In addition to handling foreground states, a well-designed mobile application must also have the ability to handle background or quit states. This includes the use of the getInitialLink method to detect whether the application was opened via a link while in a background state or after it has fully quit. This feature allows for a seamless user experience, as users can easily return to the application and pick up where they left off without having to manually navigate back to their previous location.

By incorporating this functionality, mobile applications can provide a more convenient and efficient experience for their users, making them more likely to continue using the application and recommending it to others.

const DeepLinkingConfig: LinkingOptions = {
prefixes: ['<https://safeby.com.br>'],
config: {
screens: {
ResetPasswordScreen: 'reset_password'
}
},
subscribe(listener) {
const onReceiveURL = ({ url }: { url: string }) => listener(url);

// Listen to incoming links from deep linking
Linking.addEventListener('url', onReceiveURL);

// listen to firebase dynamic link
const unsubscribeForegroundLinkingEvents = dynamicLinks().onLink(link => {
if (link.url) {
listener(link.url);
}
});

// handle background and quit state
dynamicLinks()
.getInitialLink()
.then(link => {
if (link && link.url) {
listener(link.url);
}
});

return () => {
// Clean up the event listeners
Linking.removeEventListener('url', onReceiveURL);
unsubscribeForegroundLinkingEvents();
};
}
};

After that, you need to add this configuration inside your <NavigationContainer>, look:

import {NavigationContainer} from '@react-navigation/native';

<NavigationContainer linking={DeepLinkingConfig}>
{/*
All your contexts or screens go here
*/}
</NavigationContainer>

With those few lines of code, you have the power to do very fluid redirections inside your app.

As a bonus, I will give you an extra tip to configure your “404 route”:

const config = {
screens: {
ResetPasswordScreen: 'reset_password',
NotFound: '*',
},
};

Now your imagination can fly around and make your app better.

Cheers

--

--

Luan Castheloge

Front-end engineer in activity. Data enthusiast in stand-by.