Problem
On the expense report transaction list, each row called useTransactionViolations, which subscribes to Onyx per transaction multiple times. With many rows in a virtualized FlashList, that becomes N rows × several subscriptions — any Onyx update can trigger re-renders across many rows, and list recycling keeps those subscriptions active while scrolling. This matches the anti-pattern of calling useOnyx inside list item render paths (PERF-3).
Solution
Hoists transaction violation filtering from per-row useOnyx subscriptions to the parent MoneyRequestReportTransactionList, which already subscribes to the full TRANSACTION_VIOLATIONS collection for RBR sorting. A shared getVisibleTransactionViolations helper filters violations once at the list level and passes them as stable props to each row, using a stable EMPTY_VIOLATIONS reference for rows with no violations to keep FlashList row prop identity stable.
PR
#91958
Issue Owner
Current Issue Owner: @aimane-chnaif
Problem
On the expense report transaction list, each row called
useTransactionViolations, which subscribes to Onyx per transaction multiple times. With many rows in a virtualized FlashList, that becomes N rows × several subscriptions — any Onyx update can trigger re-renders across many rows, and list recycling keeps those subscriptions active while scrolling. This matches the anti-pattern of callinguseOnyxinside list item render paths (PERF-3).Solution
Hoists transaction violation filtering from per-row
useOnyxsubscriptions to the parentMoneyRequestReportTransactionList, which already subscribes to the fullTRANSACTION_VIOLATIONScollection for RBR sorting. A sharedgetVisibleTransactionViolationshelper filters violations once at the list level and passes them as stable props to each row, using a stableEMPTY_VIOLATIONSreference for rows with no violations to keep FlashList row prop identity stable.PR
#91958
Issue Owner
Current Issue Owner: @aimane-chnaif