-
Notifications
You must be signed in to change notification settings - Fork 821
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
[react/primitive] React 18 – Flush discrete CustomEvent
dispatch calls
#1378
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
andy-hook
force-pushed
the
discrete-custom-events
branch
from
May 9, 2022 09:53
f963f73
to
9d02944
Compare
andy-hook
changed the title
Flush discrete
[core/primitive] React 18 – Flush discrete May 9, 2022
CustomEvent
dispatch callsCustomEvent
dispatch calls
andy-hook
commented
May 9, 2022
andy-hook
commented
May 9, 2022
@@ -23,7 +23,8 @@ | |||
"@radix-ui/react-use-layout-effect": "workspace:*" | |||
}, | |||
"peerDependencies": { | |||
"react": "^16.8 || ^17.0 || ^18.0" | |||
"react": "^16.8 || ^17.0 || ^18.0", | |||
"react-dom": "^16.8 || ^17.0 || ^18.0" |
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.
Will have to re-review these with the change of package so I'm skipping for now.
|
benoitgrelard
approved these changes
May 10, 2022
benoitgrelard
changed the title
[core/primitive] React 18 – Flush discrete
[react/primitive] React 18 – Flush discrete May 10, 2022
CustomEvent
dispatch callsCustomEvent
dispatch calls
A great level of detail has been added here in the description and in the comment in the code 👍 |
This was referenced May 11, 2022
luisorbaiceta
pushed a commit
to luisorbaiceta/primitives
that referenced
this pull request
Jul 21, 2022
…ls (radix-ui#1378) * Flush dispatch inside discrete handlers * Versions * Annotate * Move util, update deps * Update annotation * Versions * Fix example in annotation * Rervert format in primitive, versions
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #1287
Supersedes #1292
Big thanks to @Andarist for providing great insight into a resolution. This change is mostly equivalent though with the additional goal of providing a clear heuristic for when this is necessary and applying the change to all applicable code.
Context
One of the core changes in React 18 is the introduction of consistent batching across all event handlers, this differs from 17 where only certain events would be subject to batching. As a result, certain state updates are now batched where before they were not, creating issues like those seen in #1287
Event priorities
React assigns priorities to updates based on the type of user interaction (
discrete
,continuous
,default
),discrete
is an important distinction as it allows updates from those handlers to be made immediately. As stated in #1292 (comment) the way that React determines this priority is by usage ofwindow.event
.Because custom event types are unable to be assessed in this way, they fall through to
default
. In most cases this wouldn’t be a problem, but in the case ofContextMenu
our code structure is such that there is an implicit expectation for one update to commit before another.Why this can be problematic
In the case of
ContextMenu
, the incorrect behaviour is caused by the unexpected batching of updates inpointerdown
andcontextmenu
, while the execution order remains correct (pointerdown
->contextmenu
), the resulting state change is batched in 18, resulting in no update toopen
. As the effect cleanup is no longer cycled by moving throughfalse
->true
pointer-events: none;
does not get removed and our handler incontextmenu
is blocked.You can see and compare the behaviour in this example.
A heuristic for consistency
Given our understanding of how React splits priorities for updates, and that the intention for immediate user interaction i.e.
discrete
events is to not defer,dispatchDiscreteCustomEvent
should be used whenever a custom event type is dispatched from adiscrete
handler. This is the recommendation from the core team.Internal p riorities for these types can be found here
Use of
Event
vsCustomEvent
I’ve changed every usage of the the
Event
constructor to beCustomEvent
when a custom type is provided, this is a style change as either constructor is susceptible (it’s important to remember priority is inferred by the type passed, not which constructor used) the hope being that staying consistent will make deciding when to usedispatchDiscreteCustomEvent
easier.e.g.