-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
Proposal here
Background
The root Expensify component serves two roles: it orchestrates application lifecycle (Onyx migration, splash screen, navigation, authentication) and renders six global UI elements that stay mounted for the entire session — GrowlNotification, DelegateNoAccessModalProvider, EmojiPicker, UpdateAppModal, ProactiveAppReviewModalManager, and ScreenShareRequestModal. These modals are stateless relative to the parent; they manage visibility internally or via imperative refs.
Expensify subscribes to five Onyx keys, several of which (LAST_VISITED_PATH, LAST_ROUTE) update during routine navigation. Because eslint-disable directives in the component cause React Compiler to bail out, every re-render produces fresh JSX references for all children — forcing React to walk each child fiber even when nothing changed. Profiling on web and iOS confirms the six modal fibers appear in 97–99% of commits, each costing ~0.5–2ms of reconciliation self-time despite their render functions being ~0.1ms no-ops.
Problem
When Expensify re-renders due to routine navigation-driven Onyx updates, if React reconciles the six co-located global modal subtrees that have no dependency on the changed state, then ~3–8ms of JS thread time per commit is wasted on fiber traversal that produces zero visual changes.
Solution
Move the six global modals out of Expensify and into a dedicated React.memo-wrapped child component. The new component owns only the state it needs (a single rarely-changing prop and one Onyx subscription), so React.memo's shallow comparison bails out on virtually every parent re-render — letting React skip the entire modal subtree instead of walking it. This eliminates ~3–8ms of wasted reconciliation per commit without changing any modal behaviour or visual output.
Measured improvements
- ~ 20% for web
- ~7 % for native
Scenario & measurements in the 🧵
Draft PR here
Issue Owner
Current Issue Owner: @jmusialUpwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~022034235732288543075
- Upwork Job ID: 2034235732288543075
- Last Price Increase: 2026-03-18
Metadata
Metadata
Assignees
Labels
Type
Projects
Status