Reputation: 228
I have a react native app, on the Home Screen I have the code to open the deep link. I check if the deep link exists using Linking.getInitialURL()
and then I redirect the user if the initialUrl exists, this flow works fine but the deep link doesn't get cleared.
For example,if I click on the deep link
myapp://home/gallery it takes me to a Gallery screen. When I click on Go Home button on the Gallery screen, I go to the Home Screen. But Linking.getInitialURL()
detects the myapp://home/gallery link agan and redirects the user back to the Gallery screen. Only after this, if I go to the Home screen the initialUtl is null. How can I clear the Linking.getInitialURL()
after the link has been opened already the first time, why the react-native doesn't detect it?
I tried to check Linking.getInitialURL()
every time screen focuses( by refreshing the screen) but still
Linking.getInitialURL()
is returning the deep link first time the user goes to home from gallery.
Any help and advise is appreciated.
Edit (added code)
// Home screen
useEffect(()=> {
const getLink = async () => {
const link = Linking.getInitialURL()
if (link){
await Linking.openURL(url)}
}
getLink()
},[])
Upvotes: 4
Views: 3955
Reputation: 1
I've found a solution that works for our needs. The issue was that the url provided from the getInitialUrl (if the app was opened from a deeplink situation), matched the url provided from the eventListener. So the app did not see a change, because the url was the same.
What I did was to generate an unique deeplink url by adding a timestamp into it.
my-app:///deeplink/:timestamp/path/to/my/page
.
Then I can listen to it by using the Linking.useUrl()
hook. The following example comes straight from the app as I needed the parsed data instead of the full url. But you can figure it out :)
export default function useUrl() {
const url = Linking.useURL(); // Hook to listen for deep links
const [parsedUrl, setParsedUrl] = useState<ParsedURL>();
useEffect(() => {
if (!url) {
setParsedUrl(undefined);
return;
}
setParsedUrl(Linking.parse(url));
}, [url]);
return { ...parsedUrl };
}
Might not be a solution that will work for everyone, as the url might not be unique every time. But at least it's a way. Hope it helps!
Upvotes: 0
Reputation: 2858
You have to handle the URL logic yourself.
Ideally check for initial URL and on every change handle URL accordingly.
const onChange = (event: { url: string }) => handleUrl(event.url)
const handleUrl = async (url: string) => {
// your logic...
}
useEffect(() => {
getInitialURL().then((url) => {
url && handleUrl(url)
})
const subscription = addEventListener('url', onChange)
return () => subscription.remove()
}, [])
This way you sure about every change of the URL.
Upvotes: 0
Reputation: 1
I had a similar issue recently and you can get that behaviour by using Linking.addEventListener('url', handleOpenURL);
.
The event will be triggered only when the user clicks on the external link, and it will not be called when the App is "active".
https://docs.expo.dev/versions/latest/sdk/linking/#linkingaddeventlistenertype-handler
useEffect(() => {
Linking.addEventListener('url', handleOpenURL);
},[])
const handleOpenURL = (_url) => {
console.log(_url)
// open the URL
}
Upvotes: 0
Reputation: 31
Storing the link in a useState didn't work for my use case as I need it to be possible that a user clicks on a link twice in a row.
So I found a way by replacing the URL using Linking.openURL()
and changing the URL with that. after that not handling that new URL
Upvotes: 0
Reputation: 95
Perhaps in your case you can store the link in central state (like redux) and compare the link which is about to be opened with the one in central state.
Also, I think RN recommends checking a link with canOpenURL before opening it.
Something like this
const { centrallyStoredDeepLink } = someCentralStore;
// Home screen
useEffect(()=> {
const getLink = async () => {
const link = Linking.getInitialURL()
if (link && link !== centrallyStoredDeeplink && (await Linking.canOpenURL(link)){
centrallyStoredDeepLink = link; //You'll have to use your stores code for setting here
await Linking.openURL(url)}
}
getLink()
},[])
Upvotes: 0
Reputation: 356
you are using useEffect() and as you configured it it probably fires when you load the Home screen - please verify the same with some logs.
In general I would not specify the function within the useEffect block and use a const with useState()
to store the state for link. Then you can put the same in the [linkState]
brackets in useEffect, thus useEffect will only fire when the linkState has changed.
Additionally you are working here with deep links, then I would rather have the code for the same in the navigation index.js
. That will allow you to avoid any side effects like you are facing.
Upvotes: 0