react/scripts
Andrew Clark 09c8d25633
Move update scheduling to microtask (#26512)
When React receives new input (via `setState`, a Suspense promise
resolution, and so on), it needs to ensure there's a rendering task
associated with the update. Most of this happens
`ensureRootIsScheduled`.

If a single event contains multiple updates, we end up running the
scheduling code once per update. But this is wasteful because we really
only need to run it once, at the end of the event (or in the case of
flushSync, at the end of the scope function's execution).

So this PR moves the scheduling logic to happen in a microtask instead.
In some cases, we will force it run earlier than that, like for
`flushSync`, but since updates are batched by default, it will almost
always happen in the microtask. Even for discrete updates.

In production, this should have no observable behavior difference. In a
testing environment that uses `act`, this should also not have a
behavior difference because React will push these tasks to an internal
`act` queue.

However, tests that do not use `act` and do not simulate an actual
production environment (like an e2e test) may be affected. For example,
before this change, if a test were to call `setState` outside of `act`
and then immediately call `jest.runAllTimers()`, the update would be
synchronously applied. After this change, that will no longer work
because the rendering task (a timer, in this case) isn't scheduled until
after the microtask queue has run.

I don't expect this to be an issue in practice because most people do
not write their tests this way. They either use `act`, or they write
e2e-style tests.

The biggest exception has been... our own internal test suite. Until
recently, many of our tests were written in a way that accidentally
relied on the updates being scheduled synchronously. Over the past few
weeks, @tyao1 and I have gradually converted the test suite to use a new
set of testing helpers that are resilient to this implementation detail.

(There are also some old Relay tests that were written in the style of
React's internal test suite. Those will need to be fixed, too.)

The larger motivation behind this change, aside from a minor performance
improvement, is we intend to use this new microtask to perform
additional logic that doesn't yet exist. Like inferring the priority of
a custom event.
2023-03-31 13:04:08 -04:00
..
babel Upgrade prettier (#26081) 2023-01-31 08:25:05 -05:00
bench Upgrade prettier (#26081) 2023-01-31 08:25:05 -05:00
circleci Add snapshot testing on e2e test failure (#24672) 2022-06-06 10:36:58 -07:00
devtools Bypass packages that are already published when confirmed by users (#26141) 2023-02-10 11:28:31 -05:00
error-codes [Float][Fiber] Implement waitForCommitToBeReady for stylesheet resources (#26450) 2023-03-24 19:17:38 -07:00
eslint [Codemod] Update copyright header to Meta (#25315) 2022-10-18 11:19:24 -04:00
eslint-rules Upgrade prettier (#26081) 2023-01-31 08:25:05 -05:00
flow Move update scheduling to microtask (#26512) 2023-03-31 13:04:08 -04:00
git Remove leftover env variable logic in pre-commit hook 2015-09-01 14:35:47 -07:00
jest Remote `.internal` override from untrusted URL tests (#26372) 2023-03-11 15:46:16 -05:00
perf-counters [Codemod] Update copyright header to Meta (#25315) 2022-10-18 11:19:24 -04:00
prettier Upgrade prettier (#26081) 2023-01-31 08:25:05 -05:00
print-warnings Upgrade prettier (#26081) 2023-01-31 08:25:05 -05:00
release Add Circle CI API token to request header if available (#26519) 2023-03-30 16:06:56 -04:00
rollup [Flight] Add support BigInt support (#26479) 2023-03-29 18:23:43 +02:00
shared Split out Edge and Node implementations of the Flight Client (#26187) 2023-02-21 13:18:24 -05:00
tasks Bug: yarn flow dom does not exist, so console should suggest yarn flow dom-node (#26213) 2023-02-21 21:30:34 +01:00
yarn chore: upgrade to jest 24 (#15778) 2019-10-03 22:44:18 +05:30
authors AUTHORS 2013-09-09 23:42:54 -07:00