Perf/reduce useonyx calls in list item level#67065
Perf/reduce useonyx calls in list item level#67065roryabraham merged 20 commits intoExpensify:mainfrom
Conversation
| }; | ||
|
|
||
| function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPress}: MoneyRequestHeaderProps) { | ||
| function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPress, transactionViolations = []}: MoneyRequestHeaderProps) { |
There was a problem hiding this comment.
Let's not default to a new, empty array. Maybe we shouldn't default at all and guard later?
There was a problem hiding this comment.
The utility functions already handle undefined gracefully and defaulting to [] is a common React pattern. Without it, we'd need to add ?? [] everywhere we use it. The empty array is reused so no perf impact IMO. Why you think we should not default to an empty array?
There was a problem hiding this comment.
Oh it's just this is a new array every time, not a reused reference to an existing one.
|
@roryabraham I think the problem with failing unused styles checker is caused by #63192. Could you please confirm? |
|
@martasudol The unused styles check got fixed in #67987, if you merge main it should clear it up |
|
@martasudol Left some comments. The rest looks good |
roryabraham
left a comment
There was a problem hiding this comment.
While it's clear this results in a performance improvement, I'm concerned that it's propagating an (already well-established) bad pattern in our codebase, and that we should focus our efforts on addressing the root cause.
Not going to block on it, because I do want the product to be faster for our customers in the meantime. But overall, I don't feel great about this change.
|
@martasudol Is it ready for review? |
@roryabraham sorry, the link doesn't work for me (is it from a private channel)? Could you elaborate more what bad pattern we're talking about? Thanks in advance! |
yes, just waiting for Rory's insight about this. |
|
@dukenv0307 you can go ahead with the review, discussed in slack |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2025-08-12.at.17.38.18.movAndroid: mWeb ChromeScreen.Recording.2025-08-12.at.17.32.26.moviOS: HybridAppScreen.Recording.2025-08-12.at.17.45.55.moviOS: mWeb SafariScreen.Recording.2025-08-12.at.17.31.50.movMacOS: Chrome / SafariScreen.Recording.2025-08-12.at.17.30.12.mov |
|
🚀 Deployed to staging by https://github.com/roryabraham in version: 9.1.94-0 🚀
|
|
🚀 Deployed to production by https://github.com/marcaaron in version: 9.1.94-4 🚀
|
|
🚀 Deployed to staging by https://github.com/roryabraham in version: 9.1.95-0 🚀
|
|
🚀 Deployed to production by https://github.com/AndrewGable in version: 9.1.95-1 🚀
|

Explanation of Change
Fixed Issues
$ #67165
PROPOSAL: Reduce
useOnyxcalls on list-item level inTransactionItemRowRBRWithOnyx.Background:
The transaction list displays many items per report, each rendering with related data like violations. These components rely on hooks to fetch the data required for each item.
Problem:
When each transaction item makes multiple data subscriptions via
useTransactionViolationshook, it causes excessive re-renders and slowness in large transaction lists.Solution:
Move violation data fetching to the parent transaction list component using
useReportWithTransactionsAndViolations, which performs a single shared subscription. Pass the resulting violation data down as props to child components likeTransactionItemRowRBRWithOnyxandMoneyRequestHeader. This pattern reduces subscriptions from N×4 per report to 1, significantly improving rendering performance while preserving all existing functionality.Tests
Create a new expense with missing receipt
Verify: "Missing receipt" violation appears
Add the receipt
Verify: Violation disappears
Hold an expense
Verify: Hold status shows correctly
Verify that no errors appear in the JS console
Offline tests
Same as Tests.
QA Steps
Same as Tests.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))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
Nagranie.z.ekranu.2025-07-25.o.09.33.15.mov
Android: mWeb Chrome
Nagranie.z.ekranu.2025-07-25.o.09.34.50.mov
iOS: Native
Nagranie.z.ekranu.2025-07-25.o.09.25.57.mov
iOS: mWeb Safari
Nagranie.z.ekranu.2025-07-25.o.09.31.25.mov
MacOS: Chrome / Safari
Nagranie.z.ekranu.2025-07-25.o.09.32.22.mov
MacOS: Desktop
Nagranie.z.ekranu.2025-07-25.o.09.35.32.mov