Skip to content

[Onyx] Remove the per-key loading status from useOnyx #104583

Open

Description

@melvin-bot

Background

Components read Onyx data with useOnyx, which returns [value, {status}]. Since react-native-onyx 3.0.117 (Expensify/react-native-onyx#834), status is loading in two cases:

  1. During startup, for every key, until Onyx.init has loaded storage into the cache.
  2. After startup, for one microtask, when a hook renders a key with no value while an Onyx.merge for that key is pending.

To track this, every useOnyx call subscribes to its key a second time and keeps an extra ref and effect. The App reads status in ~330 places, mostly through isLoadingOnyxValue. Only LocaleContextProvider and HybridAppHandler mount before Onyx.init finishes and rely on the startup status.

Problem

After startup, every useOnyx call spends an extra listener and three extra hooks on a status that is almost always loaded.

Solution

Keep only the startup loading status and stop tracking it per key.

  1. App: Add a local ESLint rule in eslint-plugin-local-rules/ that blocks new isLoadingOnyxValue imports and .status reads on useOnyx results.
  2. App: Remove status reads in batches. Keep LocaleContextProvider and HybridAppHandler as they are.
    • Batch 1: reads that are always loaded after startup (14 collection keys, 4 keys with default values; 78 reads, 51 files)
    • Workspace, including company cards (src/pages/workspace; 53 reads, 40 files)
    • Settings, including Wallet and Subscription (src/pages/settings; 46 reads, 33 files)
    • Expenses and transaction merge (src/pages/iou, src/pages/TransactionMerge; 17 reads, 14 files)
    • Reimbursement account (src/pages/ReimbursementAccount; 13 reads, 11 files)
    • Domains (src/pages/domain; 10 reads, 9 files)
    • Root handlers and other pages (src/*.tsx, other src/pages, src/libs/Navigation; 39 reads, 25 files)
    • Shared components (src/components; 25 reads, 16 files)
    • Shared hooks (src/hooks; 52 reads, 27 files)
  3. Onyx: Remove per-key loading status tracking from useOnyx. status then stays loading only until Onyx.init finishes.

Testing so far found only three places that read the status while it was loading after startup: the IOU tab navigator (selectedTab_iouRequestType), post-login onboarding (nvp_onboarding), and the company cards table when switching feeds (lastSelectedFeed_<policyID>). Disabling the per-key status locally caused no regressions in these flows.

Reported in Slack.

Issue OwnerCurrent Issue Owner: @VickyStash

Activity

  1. VickyStash commented on Oct 22, 2026

    @VickyStash
    Contributor

    UPD: first PR is in internal review #104729

  2. mountiny commented on Oct 22, 2026

    @mountiny
    Contributor

    Nice, thanks for pushing it ahead!

  3. VickyStash commented on Oct 23, 2026

    @VickyStash
    Contributor

    First PR is ready for review: #104729

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions