fix: save button loading infinitely when save cropped receipt#84418
Conversation
|
@hungvu193 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
| const saveCrop = useCallback(() => { | ||
| if (!transaction?.transactionID || !sourceUri || !isImage || !cropRect) { | ||
| if (!transaction?.transactionID || !sourceUri || !isImage || !cropRect || cropRect.width < 1 || cropRect.height < 1) { | ||
| setIsCropping(false); |
There was a problem hiding this comment.
❌ CONSISTENCY-3 (docs)
The two lines setIsCropping(false); setCropRect(null); duplicate the logic already encapsulated in exitCropMode (defined at line 321). The .then() success path (lines 382-384) also contains the same pair of calls. Reusing exitCropMode() here would eliminate the duplication and keep the "exit crop mode" behavior defined in one place.
Suggested fix — call exitCropMode() instead of the two inline setters, and add it to the useCallback dependency array (it is stable since it has [] deps):
const saveCrop = useCallback(() => {
if (!transaction?.transactionID || !sourceUri || !isImage || !cropRect || cropRect.width < 1 || cropRect.height < 1) {
exitCropMode();
return;
}
// ...
}, [transaction?.transactionID, isDraftTransaction, sourceUri, isImage, cropRect, receiptFilename, policyCategories, transaction?.receipt?.type, policy, exitCropMode]);The same refactor could also apply to the .then() success path (lines 382-384) where setIsCropping(false); setCropRect(null); appears again alongside setIsCropSaving(false);.
Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
There was a problem hiding this comment.
Yep. This makes sense. Let's reuse our existing logic instead 👍
There was a problem hiding this comment.
Fixed! Replaced the duplicated setIsCropping(false); setCropRect(null); calls with exitCropMode() in both the early-return guard (line 332) and the .then() success path (line 384). Also added exitCropMode to the useCallback dependency array.
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
| const saveCrop = useCallback(() => { | ||
| if (!transaction?.transactionID || !sourceUri || !isImage || !cropRect) { | ||
| if (!transaction?.transactionID || !sourceUri || !isImage || !cropRect || cropRect.width < 1 || cropRect.height < 1) { | ||
| setIsCropping(false); |
There was a problem hiding this comment.
Yep. This makes sense. Let's reuse our existing logic instead 👍
… calls Co-authored-by: Eric Han <eh2077@users.noreply.github.com>
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid.movAndroid: mWeb ChromemChromne.moviOS: HybridAppios.moviOS: mWeb Safarisafari.movMacOS: Chrome / SafariChrome.mov |
|
🚧 @srikarparsi has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/srikarparsi in version: 9.3.34-0 🚀
|
|
🚀 Deployed to production by https://github.com/luacmartins in version: 9.3.34-2 🚀
|
Explanation of Change
Fixed Issues
$ #83709
PROPOSAL: #83709 (comment)
Tests
Same as QA section
Offline tests
Same as QA section
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Screen.Recording.2026-03-06.at.11.53.51.PM.mov
Android: mWeb Chrome
Screen.Recording.2026-03-06.at.11.51.02.PM.mov
iOS: Native
Screen.Recording.2026-03-06.at.11.48.59.PM.mov
iOS: mWeb Safari
Screen.Recording.2026-03-06.at.11.50.10.PM.mov
MacOS: Chrome / Safari
Screen.Recording.2026-03-06.at.11.45.17.PM.mov