Clear finished discrete updates during commit phase#18515
Conversation
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 6f67d0a:
|
Details of bundled changes.Comparing: bce982b...6f67d0a react-dom
react-art
react-test-renderer
react-native-renderer
react-reconciler
Size changes (stable) |
Details of bundled changes.Comparing: bce982b...6f67d0a react-art
react-native-renderer
react-test-renderer
react-dom
react-reconciler
ReactDOM: size: 0.0%, gzip: 0.0% Size changes (experimental) |
|
I'm not super familiar with this code but it seems a bit fragile. Are we treating the symptom or the cause? You said:
Do we understand why? |
|
Thanks for the unit test! The underlying issue is that we're clearing the timeout without making sure the priority level that corresponds to that level is rescheduled. It's usually fine to clear a pending timeout at the beginning of a new render (in However, There are multiple ways we could fix this. My instinct is to fix it inside We should also commit your changes here, but let's fix the underlying issue first. I'll take a closer look at this. |
Make sure the suspended level is marked as pinged so that we return back to it later, in case the render we're about to start gets aborted. Generally we only reach this path via a ping, but we shouldn't assume that will always be the case.
If a root is finished at a priority lower than that of the latest pending discrete updates on it, these updates must have been finished so we can clear them now. Otherwise, a later call of `flushDiscreteUpdates` would start a new empty render pass which may cause a scheduled timeout to be cancelled.
|
Thanks again for the fix! 🎉 |
Adds a regression test for the same underlying bug as react#18515 but using pings. Test already passes, but I confirmed it fails if you revert the fix in react#18515.
* Reproduce a bug where `flushDiscreteUpdates` causes fallback never to be committed * Ping suspended level when canceling its timer Make sure the suspended level is marked as pinged so that we return back to it later, in case the render we're about to start gets aborted. Generally we only reach this path via a ping, but we shouldn't assume that will always be the case. * Clear finished discrete updates during commit phase If a root is finished at a priority lower than that of the latest pending discrete updates on it, these updates must have been finished so we can clear them now. Otherwise, a later call of `flushDiscreteUpdates` would start a new empty render pass which may cause a scheduled timeout to be cancelled. * Add TODO Happened to find this while writing a test. A JSX element comparison failed because one of them elements had a functional component as an owner, which should ever happen. I'll add a regression test later. Co-authored-by: Andrew Clark <git@andrewclark.io>
* Add another test for react#18515 using pings Adds a regression test for the same underlying bug as react#18515 but using pings. Test already passes, but I confirmed it fails if you revert the fix in react#18515. * Set nextPendingLevel after commit, too
Fix #18020
If a root is finished at a priority lower than that of the latest pending discrete updates on it, these updates must have been finished so we can clear them now. Otherwise, a later call of
flushDiscreteUpdateswould start a new empty render pass which may cause a scheduled timeout to be cancelled.