Last active
September 2, 2022 16:57
-
-
Save todd-elvers/28185a3b3e4115f275e86dfa6b831893 to your computer and use it in GitHub Desktop.
Deep link handling via React Native hooks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Note: this behavior requires deep linking to be enabled on your React Native app | |
// https://reactnative.dev/docs/linking | |
type UseDeepLinkResult = { | |
deepLink: string | null; | |
clearDeepLink: () => void; | |
}; | |
/** Captures deep links that return true when passed through `canHandleLink` */ | |
export function useDeepLink(canHandleLink: (url: string | null) => boolean): UseDeepLinkResult { | |
const [deepLink, setDeepLink] = React.useState<string | null>(null); | |
const captureDeepLink = (url: string | null) => canHandleLink(url) && setDeepLink(url); | |
React.useEffect(() => { | |
// Handles deep links that were clicked on when the app was completely closed (i.e. force closed) | |
Linking.getInitialURL().then(captureDeepLink); | |
// Handles deep links that were clicked on when the app was backgrounded/foregrounded | |
const deepLinkListener = Linking.addEventListener("url", ({ url }) => captureDeepLink(url)); | |
return () => deepLinkListener.remove(); | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, []); | |
return { | |
deepLink, | |
clearDeepLink: React.useCallback(() => setDeepLink(null), []), | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Note: this behavior requires deep linking to be enabled on your React Native app | |
// https://reactnative.dev/docs/linking | |
type DeepLinkHandlerOptions = { | |
/** Determines whether or not we should call 'handleDeepLink' for a given link */ | |
canHandleLink?: (url: string | null) => boolean; | |
handleDeepLink: (url: string | null) => void | Promise<void>; | |
}; | |
/** Captures & handles a deep link */ | |
export const useDeepLinkHandler = ({ canHandleLink = () => true, handleDeepLink }: DeepLinkHandlerOptions) => { | |
const { deepLink, clearDeepLink } = useDeepLink(canHandleLink); | |
React.useEffect(() => { | |
if (deepLink === null) return; | |
// Workaround for iOS specific behavior where something in the event loop | |
// steps on our logic and prevents our `handleDeepLink` from being called. | |
const timeout = setTimeout(async () => { | |
await handleDeepLink(deepLink); | |
clearDeepLink(); | |
}, 500); | |
return () => { | |
clearTimeout(timeout); | |
}; | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, [clearDeepLink, deepLink]); | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment