Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ff68a85a52
ℹ️ 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".
|
|
||
| /** | ||
| * If set to `true`, the key can be changed dynamically during the component lifecycle. | ||
| */ | ||
| allowDynamicKey?: boolean; | ||
|
|
||
| /** | ||
| * This will be used to subscribe to a subset of an Onyx key's data. |
There was a problem hiding this comment.
Restore dynamic-key guard or reset state on key swap
Removing allowDynamicKey and the key-change validation now permits any useOnyx() key change, but the hook still preserves resultRef/previousValueRef across key swaps and only updates when the value comparison changes in getSnapshot(). When a component switches from one key to another uncached key that currently resolves to the same value (commonly undefined), the hook can keep reporting the previous key’s status: 'loaded' instead of transitioning through loading, which breaks consumers that rely on metadata.status during navigation-driven key changes.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
I investigated this topic and the results are:
This happens when component switches from keyA to keyB, where both resolve to undefined (neither has data in storage). Even after the connection callback fires for keyB (which sets shouldGetCachedValueRef = true and marks keyB in nullishStorageKeys), the values are still equal (undefined === undefined), and previousValueRef.current is undefined (not null), so shouldUpdateResult remains false. The status is permanently stuck at 'loaded' from keyA.
However, this bug is pre-existing. The removed useEffect was purely a validation guard - it threw errors for disallowed key changes. It performed zero state management. The getSnapshot logic is completely unchanged by this PR.
The same bug already affects:
- Collection member key changes (e.g.,
collection_id1→collection_id2) - these were always allowed withoutallowDynamicKey - Any key change when
allowDynamicKey: truewas explicitly set
The fully-triggering case (both undefined) requires:
- The old key had no stored data AND was already loaded
- The new key also has no stored data
- A consumer relies on metadata.status to show a loading state
This is a narrow scenario. In Expensify's codebase, data is typically available in Onyx before navigation (optimistic updates, prefetching), making simultaneous undefined states uncommon.
We could try fixing this, but this would require changes in the snapshot logic, which is not in the scope of this issue. Would you like me to try to fix this edge case or are we ok with it being here as it is narrow and pre-existing?
There was a problem hiding this comment.
Can you please create a new issue for it, but we dont have to fix it in this pr! thank you
There was a problem hiding this comment.
Here is the issue - Expensify/App#85416. Do you think it makes sense to add it as a sub-issue of Expensify/App#80355?
CC: @mountiny @fabioh8010
|
Reviewing... |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppandroid_native.mp4Android: mWeb Chromeandroid_chrome.mp4iOS: HybridAppios_native.mp4iOS: mWeb Safariios_safari.mp4MacOS: Chrome / Safariweb_chrome.mp4 |
luacmartins
left a comment
There was a problem hiding this comment.
Why do we have changes to package-lock.json?
|
@luacmartins my bad, removed them. |
|
@JKobrynski thank you! |
Details
Related Issues
$ Expensify/App#80096
Automated Tests
This PR only removes a feature, so some tests had to be removed. No tests have been added.
Manual Tests
Prerequisites:
In order to test this PR, you have to run E/App with this branch linked as the source of Onyx library
Log into the app
Open Search, perform a query, verify results render correctly
Click into a search result, verify report/transaction data loads
Navigate back to search, change the query, verify new results appear
Switch between different search tabs (expenses, reports, etc.)
Navigate between multiple reports quickly
Verify the correct report data shows each time (no stale data from the previous report)
Open a report, navigate away, come back — data should still be correct
View a user's profile page from a report (where reportID exists)
Verify profile data loads correctly
Author Checklist
### Related Issuessection aboveTestssectiontoggleReportand notonIconClick)myBool && <MyComponent />.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)Avataris modified, I verified thatAvataris working as expected in all cases)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
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
web-compressed.mov
MacOS: Desktop