Skip to content

Commit

Permalink
Add Batched Mode (#15502)
Browse files Browse the repository at this point in the history
* Add Batched Mode

React has an unfortunate quirk where updates are sometimes synchronous
-- where React starts rendering immediately within the call stack of
`setState` — and sometimes batched, where updates are flushed at the
end of the current event. Any update that originates within the call
stack of the React event system is batched. This encompasses most
updates, since most updates originate from an event handler like
`onClick` or `onChange`. It also includes updates triggered by lifecycle
methods or effects. But there are also updates that originate outside
React's event system, like timer events, network events, and microtasks
(promise resolution handlers). These are not batched, which results in
both worse performance (multiple render passes instead of single one)
and confusing semantics.

Ideally all updates would be batched by default. Unfortunately, it's
easy for components to accidentally rely on this behavior, so changing
it could break existing apps in subtle ways.

One way to move to a batched-by-default model is to opt into Concurrent
Mode (still experimental). But Concurrent Mode introduces additional
semantic changes that apps may not be ready to adopt.

This commit introduces an additional mode called Batched Mode. Batched
Mode enables a batched-by-default model that defers all updates to the
next React event. Once it begins rendering, React will not yield to
the browser until the entire render is finished.

Batched Mode is superset of Strict Mode. It fires all the same warnings.
It also drops the forked Suspense behavior used by Legacy Mode, in favor
of the proper semantics used by Concurrent Mode.

I have not added any public APIs that expose the new mode yet. I'll do
that in subsequent commits.

* Suspense in Batched Mode

Should have same semantics as Concurrent Mode.

* Use RootTag field to configure type of root

There are three types of roots: Legacy, Batched, and Concurrent.

* flushSync should not flush batched work

Treat Sync and Batched expiration times separately. Only Sync updates
are pushed to our internal queue of synchronous callbacks.

Renamed `flushImmediateQueue` to `flushSyncCallbackQueue` for clarity.
  • Loading branch information
acdlite authored May 13, 2019
1 parent 9382fec commit 3776d2e
Showing 1 changed file with 2 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/ReactTestRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import ReactVersion from 'shared/ReactVersion';
import act from './ReactTestRendererAct';

import {getPublicInstance} from './ReactTestHostConfig';
import {ConcurrentRoot, LegacyRoot} from 'shared/ReactRootTags';

type TestRendererOptions = {
createNodeMock: (element: React$Element<any>) => any,
Expand Down Expand Up @@ -439,7 +440,7 @@ const ReactTestRendererFiber = {
};
let root: FiberRoot | null = createContainer(
container,
isConcurrent,
isConcurrent ? ConcurrentRoot : LegacyRoot,
false,
);
invariant(root != null, 'something went wrong');
Expand Down

0 comments on commit 3776d2e

Please sign in to comment.