Repository navigation
Clear delete navigate back URL when the deleted expense screen unmounts #105220
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
base: main
Are you sure you want to change the base?
Changes from 11 commits
13048d9
8f27a00
349b726
67b98ba
8859381
592cf6b
5fa19e0
0124f66
a6171a7
fc6be12
6e8abda
7042e80
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import {doesDeleteNavigateBackUrlIncludeDuplicatesReview} from '@libs/TransactionNavigationUtils'; | ||
|
|
||
| import {clearDeleteTransactionNavigateBackUrl, clearDeleteTransactionNavigateBackUrlAfterTransitions} from '@userActions/Report'; | ||
|
|
||
| import ONYXKEYS from '@src/ONYXKEYS'; | ||
|
|
||
| import {useEffect} from 'react'; | ||
| import Onyx from 'react-native-onyx'; | ||
|
|
||
| /** Clears the delete navigate back URL on unmount, since native stack never renders a popped screen unfocused. */ | ||
| function useClearDeleteTransactionNavigateBackUrlOnUnmount(shouldClear: boolean) { | ||
| useEffect(() => { | ||
| if (!shouldClear) { | ||
| return; | ||
| } | ||
| return () => | ||
| clearDeleteTransactionNavigateBackUrlAfterTransitions(() => { | ||
| // Read when the clear fires, the unmounted screen may never have received the URL. | ||
| Onyx.get(ONYXKEYS.RAM_ONLY_PENDING_TRANSACTION_DELETE_URL).then((url) => { | ||
| if (!url || doesDeleteNavigateBackUrlIncludeDuplicatesReview(url)) { | ||
| return; | ||
| } | ||
| requestAnimationFrame(clearDeleteTransactionNavigateBackUrl); | ||
| }); | ||
| }); | ||
| }, [shouldClear]); | ||
| } | ||
|
|
||
| export default useClearDeleteTransactionNavigateBackUrlOnUnmount; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,9 @@ | ||
| import useClearDeleteTransactionNavigateBackUrlOnUnmount from '@hooks/useClearDeleteTransactionNavigateBackUrlOnUnmount'; | ||
| import useOnyx from '@hooks/useOnyx'; | ||
|
|
||
| import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; | ||
| import TransitionTracker from '@libs/Navigation/TransitionTracker'; | ||
| import {isReportTransactionThread} from '@libs/ReportUtils'; | ||
| import {doesDeleteNavigateBackUrlIncludeDuplicatesReview} from '@libs/TransactionNavigationUtils'; | ||
|
|
||
| import {clearDeleteTransactionNavigateBackUrl} from '@userActions/Report'; | ||
|
|
@@ -10,14 +13,20 @@ import ONYXKEYS from '@src/ONYXKEYS'; | |
| import {useIsFocused} from '@react-navigation/native'; | ||
| import {useEffect} from 'react'; | ||
|
|
||
| type DeleteTransactionNavigateBackHandlerProps = { | ||
| /** The reportID of the report screen this handler is mounted in */ | ||
| reportID: string | undefined; | ||
| }; | ||
|
|
||
| /** | ||
| * Component that does not render anything but isolates the NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL | ||
| * Component that does not render anything but isolates the RAM_ONLY_PENDING_TRANSACTION_DELETE_URL | ||
| * subscription from ReportScreen. Clears the URL after interactions complete | ||
| * when the report is no longer focused. | ||
| */ | ||
| function DeleteTransactionNavigateBackHandler() { | ||
| function DeleteTransactionNavigateBackHandler({reportID}: DeleteTransactionNavigateBackHandlerProps) { | ||
| const isFocused = useIsFocused(); | ||
| const [deleteTransactionNavigateBackUrl] = useOnyx(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL); | ||
| const [deleteTransactionNavigateBackUrl] = useOnyx(ONYXKEYS.RAM_ONLY_PENDING_TRANSACTION_DELETE_URL); | ||
| const [isTransactionThread = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportID)}`, {selector: isReportTransactionThread}); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we subscribe to the parent report and action too?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point, updated. the handler now subscribes to the parent report and parent action too and passes them into a new pure helper isReportTransactionThreadNew, so it rechecks once the parent data loads. added a test where the parent arrives after the thread mounts |
||
|
|
||
| useEffect(() => { | ||
| if (isFocused || !deleteTransactionNavigateBackUrl) { | ||
|
|
@@ -36,6 +45,8 @@ function DeleteTransactionNavigateBackHandler() { | |
| return () => handle.cancel(); | ||
| }, [isFocused, deleteTransactionNavigateBackUrl]); | ||
|
|
||
| useClearDeleteTransactionNavigateBackUrlOnUnmount(isTransactionThread); | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also cancel the queued animation frame when a new deletion starts. Once the transition callback fires, there's no pending handle left to cancel. If another deletion sets its URL before this frame runs, the old callback clears that new URL and can show Not Found while the screen is closing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, the cancel handle now covers the whole chain: the transition, the Onyx.get result and the queued frame (cancelAnimationFrame). so a new deletion cancels it even after the transition callback already ran. added a test for that case too