-
Notifications
You must be signed in to change notification settings - Fork 48.5k
Flush discrete updates immediately in a batched context #21202
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
// TODO: Should be able to flush inside batchedUpdates, but not inside `act`. | ||
// However, `act` uses `batchedUpdates`, so there's no way to distinguish | ||
// those two cases. Need to fix this before exposing flushDiscreteUpdates | ||
// as a public API. |
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.
I don't agree that we shouldn't flush inside act
. act
was supposed to test closer to what a user sees. Batching discrete updates is not something a user can ever see.
Some history of the comment:
- changed: 73c380f
- introduced: ef4ac42#diff-4795b2bc8a2ac82f7c16985975dffe52bb4435555755f321f9ab7d76f5b48807R571-R572
Looks like there was never a follow-up mentioned when introducing this comment.
Pinging @acdlite since he changed the comment most recently.
Comparing: 7841d06...579bdc3 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: (No significant changes) |
@@ -174,8 +174,8 @@ function runActTests(label, render, unmount, rerender) { | |||
click(); | |||
click(); | |||
}); | |||
// it consolidates the 3 updates, then fires the effect | |||
expect(Scheduler).toHaveYielded([3]); |
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.
In my opinion, this was undesired behavior. A user clicking three times would see all three updates being flushed not just one. Programmatic click via DOM API would also flush three times: https://codesandbox.io/s/click-is-not-batched-re61e?file=/src/index.js:587-634
I added this to our project checklist to review when we get to other |
Note that this is not quite true: Use of It might not be helpful in practice though so maybe it should instead be a warning to add |
Thanks for the clarification. I didn't consider that scenario.
click() is probably a bad example here since that seems like an exotic use case. So I do understand that wrapping discrete even dispatches in act does make sense if we want to simulate how these events would be treated in a react event handler. However, this is not what act was promoted as.
-- https://reactjs.org/docs/testing-recipes.html#act
It's not clear to me why we'd want to test how a discrete event in another event handler would behave. In that case why not dispatch the actual event? For example function MenuItem() {
return <button onKeyDown={(event) => event.currentTarget.blur()} role="menuitem" />
}
render(<MenuItem />)
const menuitem = document.querySelector('[role="menuitem"]');
act(() => {
- menuitem.blur();
+ menuitem.dispatchEvenet(new KeyboardEvent('keydown', { bubbles: true, cancelable: true }));
}) Ideally I could take a look at every usage of
I'm tempted to try a version of |
|
Closing since it's cleared up for me now. |
Summary
Given:
Previously each update from the click was batched inside act. However, in production React will never batch updates from user clicks since these are "discrete" events. With this PR discrete updates will be flushed immediately instead of being batched.
The previous behavior resulted in bugs like #20074 not being detected via automated testing. In Material-UI we already need extra
fireDiscreteEvent.click
testing utilities that make sure click events are flushed immediately from insideact
to test certain browser behavior.Test Plan
testing-library/react-testing-library
: NOT FOR MERGE test: run with a version of act that flushes discrete events imeadiately testing-library/react-testing-library#896mui-org/material-ui
: NOT FOR MERGE test: run with a version of act that flushes discrete events imeadiately mui/material-ui#25658