Fix for - Reports - Report row shows fallback avatar when user has custom avatar#84599
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4955f23a85
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
|
|
||
| const [cardFeeds, cardFeedsResult] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER); | ||
| const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); | ||
| const [onyxPersonalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); |
There was a problem hiding this comment.
❌ PERF-11
useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST) subscribes to the entire personal details collection without a selector, and it is listed as a useMemo dependency (line 496). PERSONAL_DETAILS_LIST is a large, frequently-changing Onyx key — it updates whenever any user the current user has interacted with changes their profile. This means:
- Every unrelated personal-detail change triggers a component re-render.
- The expensive
getSections()useMemo recomputes each time becauseonyxPersonalDetailsListis in its dependency array.
Consider one of these alternatives:
- Use a ref to hold the Onyx value so it doesn't appear in the useMemo deps (the Onyx subscription still keeps it current, but the memo only recomputes when search data actually changes).
- Use a selector to extract only the account IDs / avatar fields needed, reducing the deep-equal comparison surface.
- Leverage
Onyx.connect/getPersonalDetailsForAccountID()outside the render cycle (this pattern already exists ingetReportSections).
| const [onyxPersonalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); | |
| // Option A: use a ref to avoid adding it to useMemo deps | |
| const [onyxPersonalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); | |
| const personalDetailsRef = useRef(onyxPersonalDetailsList); | |
| personalDetailsRef.current = onyxPersonalDetailsList; | |
| // Then use personalDetailsRef.current inside the useMemo callback | |
| // and remove onyxPersonalDetailsList from the dependency array. |
Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
There was a problem hiding this comment.
I don't think we can escape calling it as is.
Before a subscription like this existed per every row src/components/ReportActionAvatars/index.tsx -> src/components/ReportActionAvatars/useReportActionAvatars.ts#59 so having it only once is an improvement.
I'll run some quick perf tests between this fix and old code using ReportActionAvatars and update here
|
Codex Review: Didn't find any major issues. Delightful! ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
There was a problem hiding this comment.
Nit: Inconsistent use of mergedPersonalDetails
The new mergedPersonalDetails is correctly used for getSearchReportAvatarProps, but fromDetails and toDetails still read from data.personalDetailsList directly:
Lines 2319 to 2323 in 82f5a09
fromDetails happens to be safe because it already falls back to getPersonalDetailsForAccountID() (which reads Onyx). However, toDetails has no such fallback — if data.personalDetailsList is missing the managerID entry, the "to" field silently resolves to emptyPersonalDetails.
For consistency (and to prevent a similar bug on the "to" side), both lookups should use mergedPersonalDetails instead of data.personalDetailsList.
what do you think ?
I think this is a great pick, would prefer to do this change in a separate PR as this is the DB fix, whould that be ok ? |
Looks fine for me .. deferring that decision to @luacmartins |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-03-09.at.17.25.08.movAndroid: mWeb ChromeScreen.Recording.2026-03-09.at.17.30.27.moviOS: HybridAppScreen.Recording.2026-03-09.at.17.25.08.moviOS: mWeb SafariScreen.Recording.2026-03-09.at.17.30.27.movMacOS: Chrome / SafariScreen.Recording.2026-03-09.at.17.21.47.mov |
abzokhattab
left a comment
There was a problem hiding this comment.
I have tested the current changes and it looks good to me
…r-resolves-to-fallback Fix for - Reports - Report row shows fallback avatar when user has custom avatar (cherry picked from commit 9def1e0) (cherry-picked to staging by luacmartins)
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚧 @luacmartins 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! 🧪🧪
|
…r-resolves-to-fallback Fix for - Reports - Report row shows fallback avatar when user has custom avatar (cherry picked from commit 9def1e0)
|
🚀 Deployed to production by https://github.com/luacmartins in version: 9.3.33-5 🚀
|
|
🚀 Cherry-picked to staging by https://github.com/luacmartins 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
$ #84472
PROPOSAL:
Tests
Precondition:
Offline tests
N/A
QA Steps
Same as tests
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
MacOS: Chrome / Safari
Screen.Recording.2026-03-09.at.15.20.12.mov