fix: connection could be called twice on set#570
Conversation
Reviewer Checklist
Screenshots/VideosAndroid: Native2024-07-23.17.22.36.movAndroid: mWeb Chrome2024-07-23.16.58.23.moviOS: Native2024-07-23.16.53.52.moviOS: mWeb Safariios-web.movMacOS: Chrome / Safariweb.movMacOS: Desktopdesktop_3OwDY93A.mp4 |
mountiny
left a comment
There was a problem hiding this comment.
Changes look good to me too, waiting for a c+ testing
Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com>
| type BaseConnectOptions = { | ||
| initWithStoredValues?: boolean; | ||
| /** | ||
| * If true, it will call the callback function even if the value might hasn't changed. |
There was a problem hiding this comment.
I think you left an error here, right? "Value might hasn't changed"
There was a problem hiding this comment.
Hm maybe my wording wasn't precise here.
When this value is true it can happen that the Onyx.conenct callback gets called with the same value multiple times (basically bypass the improvement)
Do you have an idea how to rephrase it to make it more obvious / better understandable?
There was a problem hiding this comment.
Currently discussing if this param is really needed
|
hm, lets wait one moment before we continue, want to ask Fabio one thing who wrote the useOnxy hook. Maybe we don't need the |
|
The changes look good ! |
|
Yes, thanks for being patient with me! There was this test that failed with the changes I made: The thing is that the test case was a bit broken. In the test we change the selector function reference. In a react application that will only happen when the hook gets called again aka. the component re-renders (if we follow all strict rules, which we do). So the solution was to fix the test by simulating how in a regular react app the selector ref would change - with a |
|
@hannojg |
marcaaron
left a comment
There was a problem hiding this comment.
Changes look good. No blockers from me.
| // In a react app we expect the selector ref to change during a rerender (see selectorRef/useLiveRef) | ||
| rerender(undefined); | ||
|
|
||
| await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, {id: 'changed_id', name: 'changed_name'})); |
There was a problem hiding this comment.
| await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, {id: 'changed_id', name: 'changed_name'})); | |
| await act(async () => waitForPromisesToResolve()); | |
| expect(result.current[0]).toEqual('id - test_id, name - test_name - selector changed'); |
I think we can remove the Onyx.merge since the rerender() is enough to prove the selector changed
There was a problem hiding this comment.
ah good idea, let me check!
There was a problem hiding this comment.
We don't even need waitForPromisesToResolve() 😊 looks good?
|
@mountiny I think we are good to merge! |
|
🚀Published to npm in v2.0.58 |
|
@hannojg I noticed that these changes are causing some tests in E/App to fail. Is this expected? |
|
They are failing due to another bug in Onyx for which I have a PR to fix here: |


Details
This PR fixes cases where a call to
Onyx.setcould invoke aOnyx.connectlistener twice.For
withOnyxconnections this isn't happening, as they are already guarded by previous equal comparisons.The fix here is to add a map that will store all previous values that were send to the
Onyx.connectcallback. We can't reuse the cache here unfortunately, as it can contain values while no data has been send to the connection yet (and thus a comparison would lead to us not sending to the connection.For useOnyx I had to add a special parameter to
Onyx.connectcalledalwaysNotifywhich is false by default.useOnyxmight uses a selector to transform the data. The output of that selector can change, even though the input data stay the same.Thus for
useOnyxwe always have to call the connect callback.Related Issues
#569
Automated Tests
Manual Tests
n/a
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
Note: pressing the send button might be buggy in the recordings, its a know issue first reported here and is not related to this PR.
Android: Native
Screen.Recording.2024-07-22.at.13.11.30.mov
Android: mWeb Chrome
Screen.Recording.2024-07-22.at.12.53.24.mov
iOS: Native
Screen.Recording.2024-07-22.at.12.46.08.mov
iOS: mWeb Safari
iOS-mWeb.mov
MacOS: Chrome / Safari
web.mov
MacOS: Desktop
desktop.mov