diff --git a/README.md b/README.md index 5edcb738..26322fa0 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ yarn add @react-native-community/hooks - [useDeviceOrientation](https://github.com/react-native-community/hooks#usedeviceorientation) - [useLayout](https://github.com/react-native-community/hooks#uselayout) - [useRefresh](https://github.com/react-native-community/hooks#useRefresh) +- [useLinking](https://github.com/react-native-community/hooks#useLinking) ### `useAccessibilityInfo` @@ -153,6 +154,18 @@ const { isRefreshing, onRefresh } = useRefresh(fetch); /> ``` +### `useLinking` + +useLinking can handle incoming your app's deeplinks through the [`Linking`](https://reactnative.dev/docs/linking) API. + +```js +import {useLinking} from '@react-native-community/hooks' + +const { deepLink } = useLinking() + +console.log('Initial deep link is:', deepLink) +``` + [version-badge]: https://img.shields.io/npm/v/@react-native-community/hooks.svg?style=flat-square [package]: https://www.npmjs.com/package/@react-native-community/hooks diff --git a/src/useLinking.test.ts b/src/useLinking.test.ts new file mode 100644 index 00000000..d3eeeafb --- /dev/null +++ b/src/useLinking.test.ts @@ -0,0 +1,36 @@ +import {Linking} from 'react-native' +import {act, renderHook} from '@testing-library/react-hooks' + +import {useLinking} from './useLinking' + +jest.mock('react-native', () => ({ + Linking: { + addEventListener: jest.fn((_, fn) => ({remove: jest.fn()})), + getInitialURL: jest.fn(() => Promise.resolve()), + openSettings: jest.fn(() => Promise.resolve()), + canOpenURL: jest.fn(() => Promise.resolve(true)), + openURL: jest.fn((url: string) => Promise.resolve()), + }, +})) + +describe('useLinking', () => { + it('should return deeplink as null', () => { + const {result, waitForNextUpdate} = renderHook(() => useLinking()) + + waitForNextUpdate() + + expect(result.current.deepLink).toBe(null) + }) + + it('calls getInitialURL with initial deeplink url', async () => { + const url = 'app://magic_screen' + const getInitialURLSpy = jest.spyOn(Linking, 'getInitialURL') + getInitialURLSpy.mockResolvedValueOnce(url) + + const {result, waitForNextUpdate} = renderHook(() => useLinking()) + + await waitForNextUpdate() + + expect(result.current.deepLink).toBe('app://magic_screen') + }) +}) diff --git a/src/useLinking.ts b/src/useLinking.ts new file mode 100644 index 00000000..6ad87a9d --- /dev/null +++ b/src/useLinking.ts @@ -0,0 +1,24 @@ +import {useEffect, useState} from 'react' +import {Linking} from 'react-native' + +const useLinking = () => { + const [deepLink, setDeepLink] = useState(null) + + const handleURLChange = (event: {url: string}) => { + setDeepLink(event.url) + } + + useEffect(() => { + Linking.getInitialURL().then((url: string) => setDeepLink(url)) + }, []) + + useEffect(() => { + const listener = Linking.addEventListener('url', handleURLChange) + + return () => listener.remove() + }, []) + + return {deepLink} +} + +export {useLinking}