-
Notifications
You must be signed in to change notification settings - Fork 581
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: avoid prefetching when following deeplinks (#11097)
* fix: avoid prefetching when following deeplinks * fix: avoid making home view query requests when opening deep links Co-authored-by: Ole <[email protected]> Co-authored-by: Anandaroop Roy <[email protected]> * fix: don't treat / as a deep link Prior to this change we were rendering a blank home screen in the event of navigating directly to / * fix: switch back to matching route to module This will be more reliable in the case of various edges cases that might bring the user to the home screen * fix: code review suggestions Co-authored-by: Ole <[email protected]> Co-authored-by: Mounir Dhahri <[email protected]> * fix(test): mock the deep link hook --------- Co-authored-by: Ole <[email protected]> Co-authored-by: Mounir Dhahri <[email protected]>
- Loading branch information
1 parent
ce85c9b
commit 0f62932
Showing
5 changed files
with
166 additions
and
11 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { renderHook } from "@testing-library/react-hooks" | ||
import { matchRoute } from "app/routes" | ||
import { useIsDeepLink } from "app/utils/hooks/useIsDeepLink" | ||
import { Linking } from "react-native" | ||
|
||
const mockUseIsFocusedMock = jest.fn() | ||
jest.mock("@react-navigation/native", () => ({ | ||
useIsFocused: () => mockUseIsFocusedMock(), | ||
})) | ||
|
||
jest.mock("react-native", () => ({ | ||
Linking: { | ||
getInitialURL: jest.fn(), | ||
}, | ||
})) | ||
|
||
jest.mock("app/routes", () => ({ | ||
matchRoute: jest.fn(), | ||
})) | ||
|
||
describe("useIsDeepLink", () => { | ||
const mockLinkingGetInitialURL = Linking.getInitialURL as jest.Mock | ||
const mockMatchRoute = matchRoute as jest.Mock | ||
|
||
it("should return true if opened from a deep link", async () => { | ||
// Setup the mock to return the specific URL | ||
mockLinkingGetInitialURL.mockResolvedValue("artsy:///artwork/foo") | ||
mockMatchRoute.mockReturnValue({ type: "match", module: "Artwork" }) | ||
mockUseIsFocusedMock.mockReturnValue(true) | ||
|
||
// Render the hook under test | ||
const { result, waitForNextUpdate } = renderHook(() => useIsDeepLink()) | ||
|
||
// Wait for async effects to resolve | ||
await waitForNextUpdate() | ||
|
||
expect(result.current).toEqual({ | ||
isDeepLink: true, | ||
}) | ||
expect(mockUseIsFocusedMock).toHaveBeenCalled() | ||
expect(mockLinkingGetInitialURL).toHaveBeenCalled() | ||
expect(mockMatchRoute).toHaveBeenCalled() | ||
}) | ||
|
||
it("should return false if not opened from a deep link", async () => { | ||
// Setup the mock to return null | ||
mockLinkingGetInitialURL.mockResolvedValue(null) | ||
mockUseIsFocusedMock.mockReturnValue(true) | ||
|
||
// Render the hook under test | ||
const { result, waitForNextUpdate } = renderHook(() => useIsDeepLink()) | ||
|
||
// Wait for async effects to resolve | ||
await waitForNextUpdate() | ||
|
||
expect(result.current.isDeepLink).toEqual(false) | ||
expect(mockUseIsFocusedMock).toHaveBeenCalled() | ||
expect(mockLinkingGetInitialURL).toHaveBeenCalled() | ||
expect(mockMatchRoute).toHaveBeenCalled() | ||
}) | ||
|
||
it("should return false if opened from a link to /", async () => { | ||
// Setup the mock to return null | ||
mockLinkingGetInitialURL.mockResolvedValue("artsy:///") | ||
mockMatchRoute.mockReturnValue({ type: "match", module: "Home" }) | ||
mockUseIsFocusedMock.mockReturnValue(true) | ||
|
||
// Render the hook under test | ||
const { result, waitForNextUpdate } = renderHook(() => useIsDeepLink()) | ||
|
||
// Wait for async effects to resolve | ||
await waitForNextUpdate() | ||
|
||
expect(result.current.isDeepLink).toEqual(false) | ||
expect(mockUseIsFocusedMock).toHaveBeenCalled() | ||
expect(mockLinkingGetInitialURL).toHaveBeenCalled() | ||
expect(mockMatchRoute).toHaveBeenCalled() | ||
}) | ||
}) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { useIsFocused } from "@react-navigation/native" | ||
import { matchRoute } from "app/routes" | ||
import { useEffect, useState } from "react" | ||
import { Linking } from "react-native" | ||
|
||
/** | ||
* This is a hook that returns whether or not the user came from a deep link | ||
* (defined as a direct navigation to a route other than "/"). | ||
* | ||
* This can be used to avoid rendering content in previous screens in react-navigation history | ||
* | ||
* @returns {isDeepLink: boolean | null}` isDeepLink` is true if the user came from a deep link. Initially, it is set to `null` while retrieving the deep link URL asynchronously and will be set to `false` if retrieving the `URL` fails. | ||
*/ | ||
export const useIsDeepLink = () => { | ||
const [isDeepLink, setIsDeepLink] = useState<boolean | null>(null) | ||
|
||
const isFocused = useIsFocused() | ||
|
||
useEffect(() => { | ||
// When the user comes back from a deep link, | ||
// we want to show content again | ||
if (isFocused && isDeepLink === true) { | ||
setIsDeepLink(false) | ||
} | ||
}, [isFocused]) | ||
|
||
useEffect(() => { | ||
Linking.getInitialURL() | ||
.then((url) => { | ||
if (!url) { | ||
setIsDeepLink(false) | ||
return | ||
} | ||
|
||
const result = matchRoute(url) | ||
const isExternalUrl = result.type === "external_url" | ||
const isHomeLink = result.type === "match" && result.module === "Home" | ||
const shouldTreatAsDeepLink = !isHomeLink && !isExternalUrl | ||
|
||
setIsDeepLink(shouldTreatAsDeepLink) | ||
}) | ||
.catch((error) => { | ||
console.error("Error getting initial URL", error) | ||
setIsDeepLink(false) | ||
}) | ||
}, []) | ||
|
||
return { | ||
isDeepLink, | ||
} | ||
} |
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