-
Notifications
You must be signed in to change notification settings - Fork 4.7k
useSelect: improve transition from async to sync mode #40680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| // initial render + rerender with isAsync=false + store state update | ||
| expect( TestComponent ).toHaveBeenCalledTimes( 3 ); | ||
| // initial render + rerender with isAsync=false | ||
| expect( TestComponent ).toHaveBeenCalledTimes( 2 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds like a potential performance improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this happens only in a very rare condition where there actually was a pending store update when the component was switching from async to sync mode.
|
Size Change: -6 B (0%) Total Size: 1.23 MB
ℹ️ View Unchanged
|
This PR refactors
useSelectcode that makes sure that when the component is switching from async to sync mode, then the state updates scheduled while still in async mode won't be forgotten.The old code achieved that by flushing the render queue during the transition, which means synchronously calling
onStoreChangeand reading the new state from stores.The new code reads the new state from stores, too, but does it by doing a
hasLeftAsyncModecheck and callingmapSelectif the check is true. It's an addition to the set of existing checks that trigger call ofmapSelect: change of registry, change of themapSelectfunction itself (and its dependencies), and failure on previous call.Why is this change for the better? Because it removes a
renderQueue.flushcall, and concentrates allrenderQueuereferences into the effect that maintains store subscriptions and calls theonStoreChangecallback. That makes it easier to extract that effect to a separate hook, i.e., finishing the work in #40093.How to test:
Covered by unit tests, namely the "catches updates while switching from async to sync" one. See also #19286 which describes the conditions where doing the async->sync transition incorrectly can lead to UI bugs.