-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deep linking is not working when app is closed/killed #32350
Comments
I'm facing the same issue. Any solutions? |
same here. Working with react-native 0.65.1 version. |
same here |
I found a work around to handle the situation, & assuming that your app has Auth flow as well, if not here's a solution to support Auth flow for deep-linking. What i had noticed was when the app was in background the user's app state was in sync and deep link was working as expected and was showing the correct info but when I close/kill the app and open it from a deep-link then the user's data isn't found and it was failing because user's state is checked during app launch from splash screen but during an app launch through deep link it doesn't open from splash screen it directly opens the deep linked screen. So to resolve it and show the correct screen with proper info i'm adding a check on each launch when its from deep link.
import React from 'react'
import {CommonActions} from '@react-navigation/native';
import DeepLinkLoader from '../../widgets/deeplinkloader; //A loader component to show only when deep link is opened
const Profile = () => {
const [deepLoading, setDeepLoading] = React.useState(false);
let isDeepLinked = React.useRef(false);
//Handling back functionality of deep link
// If this is not handled then on press of back the app exits completely to handle that i'm setting it to route to home screen.
const onDeviceBackPress = () => {
if (isDeepLinked.current) {
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: 'HomeScreen'}],
}),
);
return true;
}
};
React.useEffect(() => {
if (user.id === undefined) {
setDeepLoading(true);
isDeepLinked.current = true;
//Storage has the `userId` which i'm fetching & making an api call to fetch the
//user details and set it to state and then load the screen
Storage.instance.getData('userId').then((id) => {
API.instance.get(`/users/${id}/all`).then((res) => {
// Adding the user to the state & setting the deep link to false to show the screen.
dispatch(addUser(res));
setDeepLoading(false);
});
});
}
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
onDeviceBackPress,
);
return () => backHandler.remove();
}, []);
// If the screen is opened from a deep link then the below loader will show
// & once the user info is set then it will show the actual screen
if (deepLoading) return <DeepLinkLoader />;
return (
<View>
//Profile info
</View>
)
}
export default Profile
When a closed app is launched from deep link it checks if user's data is found or not,
if not found then it makes an api call and sets it to the state through redux & show the screen,
incase the `userId` is also not found then it will fallback to the login screen. |
is there any solution? |
I was having same problem with I fixed it by adding "content available" on iOS . Here is link to SO I posted https://stackoverflow.com/a/70869289/4724718
|
@blueprin4 is I am facing issue in android only. |
Any solutions for opening normal deep URLs on a killed iOS app? I'm not trying to fix push-notification deep links, so can't use the Seems like it is getting sent in my Appdelegate, all the way to RCTDeviceEventEmitter. Not sure where the url falls off, but I'm guessing inside react-native iOS native code. Works on android! |
@nixolas1 I'm facing exactly the same issue, putting a setTimeout inside the async getInitialURL() {
const url = await Linking.getInitialURL();
if (url) {
setTimeout(() => {
handleDeepLinkingUrl(url);
}, 5000);
}
return url;
} EDIT <NavigationContainer linking={linking} onReady={() => { isReadyRef.current = true }}> The problem is that the navigation routes aren't ready when the app is closed, so I've put a setInterval in the linking object, to check when the Navigation Container is ready to decide when to redirect: async getInitialURL() {
const url = await Linking.getInitialURL();
if (url) {
let interval: NodeJS.Timeout | null = null;
interval = setInterval(() => {
if (isReadyRef.current) {
handleDeepLinkingUrl(url);
if (interval) {
clearInterval(interval);
}
}
}, 100);
}
return url;
} |
Nice, seems like a possible solution @vitorbetani. Could I ask where you call your getInitialUrl function? I run mine in a useEffect inside a child component, and Linking.getInitialUrl just returns nothing. |
I met the same issue (android and ios). |
hello @vitorbetani what is inside the handleDeepLinkingUrl? I would like to use your code but i cant because it said handleDeepLinkingUrl is not defined please help :( |
Hey Fernando, the |
I'm facing the same issue in iOS only. |
I'm facing the issue in iOS. |
related? |
I had the same problem, but only on ios. I've read the documentation of react native, react navigation, github issues, stack overflow questions over and over again. Nothing worked. But after all of that i implemented this: await Linking.canOpenURL(initialUrl) it works on ios with all type of deep linking variations (custom schema, https and dynamic link). Can somebody confirm this behaviour? |
Hello @vitorbetani , Sorry to ask you again! My only doubt is what navigationref we need to use to navigate to a particular screen? Can you give me an example? Please help!!! I tried using - isReadyRef.navigate("screennameABC") but getting error as "Cannot read properties of undefined (reading 'apply')" |
I tried @vitorbetani's approach and it didn't work for me on ios. Fyi, I'm currently using a less pretty approach with settimeout instead but it's working in my case
|
I had the same problem and for me, the following is working on iOS and Android: import * as Linking from 'expo-linking'
// prefix for deep-links
const prefix = Linking.createURL('/')
// config for deep-links
const config = {
screens: {
...
},
},
}
// variable for url
let deepLink
// linking config for navigator
const linking = {
prefixes: [prefix],
config,
async getInitialURL() {
// Check if app was opened from a deep link
deepLink = await Linking.getInitialURL()
// Don't handle it now - wait until Navigation is ready
console.log('DeepLink URL:', deepLink)
},
}
// open url if deepLink is defined
const openDeepLink = async () => {
if (deepLink) Linking.openURL(deepLink)
}
// check when react navigation is ready
const onNavigationReady = async () => {
// if deep link exists, open when navigation is ready
await openDeepLink()
}
function AppNavigator() {
return (
<NavigationContainer onReady={onNavigationReady} linking={linking}>
<Stack.Navigator>
<Stack.Group>
...
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
)
} |
this code worked for me |
One solution is to wait a little before load url
|
Here a little write-up how I was able to solve the issue in my application. Perhaps it is helpful. Delaying the opening of the deep link with setTimeout or similar is not a reliable solution as proposed by me earlier.
If the deep link is referring to a stack navigator (here: AppNavigator with isAuth = false) that is not yet rendered, the linking does not work.
So I'm waiting until the AppNavigator is rendered, and then open the deep link which I stored in a useRef: /*** navigation/index.jsx ***/
/*** AppNavigator.jsx ***/
|
here what i have done in my side
|
Based on https://documentation.onesignal.com/v7.0/docs/react-native-sdk#handlers
also in reactnavigation:
|
For me, my goal is to redirect the user to the specific pages when the notification is clicked.
Thanks guys! |
|
Implement ...,
config: deepLinkConfigs,
async getInitialURL() {
const url = decodeURI((await Linking.getInitialURL()) ?? '');
if (url) return url;
// Check if there is an initial firebase notification
const message = await messaging().getInitialNotification();
// Get deep link from data
// if this is undefined, the app will open the default/home page
return message?.data?.link ?? '';
},
... |
|
I was facing same issue i used some other function and it started working fine as expected dynamicLinks().onLink((item) => { as i am assuming it was happening due to listener hope this will help Thanks |
it's been a long time since this issue was opened, is anyone working on the fix? @react-native-bot |
Any news about it? |
Any updates on this? |
Description
If app in background
If app is not in background or closed
I tried some of the work arounds mentioned on stackoverflow but they dont seems to work
References: Deep linking - doesn't work if app is closed , React Native - Deep linking is not working when app is not in background (Android, iOS), Deep linking not working when app is in background state React native
React Native version:
System:
OS: macOS 10.15.7
Binaries:
Node: 16.8.0 - /usr/local/bin/node
npm: 7.22.0 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.10.1 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 14.4, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
npmPackages:
@react-native-community/cli: Not Found
react: 17.0.2 => 17.0.2
react-native: ^0.64.0 => 0.64.2
Expected Results
It should open the specific screen through deep link when the app is in closed/killed state also.
Snack, code example :
linking.js
App.js
The text was updated successfully, but these errors were encountered: