Skip to content

Commit

Permalink
Feature: Suspend commit without blocking render (#26398)
Browse files Browse the repository at this point in the history
This adds a new capability for renderers (React DOM, React Native):
prevent a tree from being displayed until it is ready, showing a
fallback if necessary, but without blocking the React components from
being evaluated in the meantime.

A concrete example is CSS loading: React DOM can block a commit from
being applied until the stylesheet has loaded. This allows us to load
the CSS asynchronously, while also preventing a flash of unstyled
content. Images and fonts are some of the other use cases.

You can think of this as "Suspense for the commit phase". Traditional
Suspense, i.e. with `use`, blocking during the render phase: React
cannot proceed with rendering until the data is available. But in the
case of things like stylesheets, you don't need the CSS in order to
evaluate the component. It just needs to be loaded before the tree is
committed. Because React buffers its side effects and mutations, it can
do work in parallel while the stylesheets load in the background.

Like regular Suspense, a "suspensey" stylesheet or image will trigger
the nearest Suspense fallback if it hasn't loaded yet. For now, though,
we only do this for non-urgent updates, like with startTransition. If
you render a suspensey resource during an urgent update, it will revert
to today's behavior. (We may or may not add a way to suspend the commit
during an urgent update in the future.)

In this PR, I have implemented this capability in the reconciler via new
methods added to the host config. I've used our internal React "no-op"
renderer to write tests that demonstrate the feature. I have not yet
implemented Suspensey CSS, images, etc in React DOM. @gnoff and I will
work on that in subsequent PRs.

DiffTrain build for [db281b3](db281b3)
  • Loading branch information
acdlite committed Mar 17, 2023
1 parent b91c209 commit e49c66b
Show file tree
Hide file tree
Showing 18 changed files with 4,679 additions and 3,215 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6854a3cf6d0e980f93a5e8ee1e546e3e31ac0869
db281b3d9cd033cdc3d63e00fc9f3153c03aa70c
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if (
}
"use strict";

var ReactVersion = "18.3.0-www-modern-2016a392";
var ReactVersion = "18.3.0-www-modern-eb67b0a3";

// ATTENTION
// When adding new symbols to this file,
Expand Down
400 changes: 281 additions & 119 deletions compiled/facebook-www/ReactART-dev.classic.js

Large diffs are not rendered by default.

400 changes: 281 additions & 119 deletions compiled/facebook-www/ReactART-dev.modern.js

Large diffs are not rendered by default.

447 changes: 234 additions & 213 deletions compiled/facebook-www/ReactART-prod.classic.js

Large diffs are not rendered by default.

447 changes: 234 additions & 213 deletions compiled/facebook-www/ReactART-prod.modern.js

Large diffs are not rendered by default.

408 changes: 287 additions & 121 deletions compiled/facebook-www/ReactDOM-dev.classic.js

Large diffs are not rendered by default.

408 changes: 287 additions & 121 deletions compiled/facebook-www/ReactDOM-dev.modern.js

Large diffs are not rendered by default.

576 changes: 297 additions & 279 deletions compiled/facebook-www/ReactDOM-prod.classic.js

Large diffs are not rendered by default.

632 changes: 325 additions & 307 deletions compiled/facebook-www/ReactDOM-prod.modern.js

Large diffs are not rendered by default.

617 changes: 318 additions & 299 deletions compiled/facebook-www/ReactDOM-profiling.classic.js

Large diffs are not rendered by default.

675 changes: 347 additions & 328 deletions compiled/facebook-www/ReactDOM-profiling.modern.js

Large diffs are not rendered by default.

408 changes: 287 additions & 121 deletions compiled/facebook-www/ReactDOMTesting-dev.classic.js

Large diffs are not rendered by default.

408 changes: 287 additions & 121 deletions compiled/facebook-www/ReactDOMTesting-dev.modern.js

Large diffs are not rendered by default.

656 changes: 337 additions & 319 deletions compiled/facebook-www/ReactDOMTesting-prod.classic.js

Large diffs are not rendered by default.

632 changes: 325 additions & 307 deletions compiled/facebook-www/ReactDOMTesting-prod.modern.js

Large diffs are not rendered by default.

388 changes: 275 additions & 113 deletions compiled/facebook-www/ReactTestRenderer-dev.classic.js

Large diffs are not rendered by default.

388 changes: 275 additions & 113 deletions compiled/facebook-www/ReactTestRenderer-dev.modern.js

Large diffs are not rendered by default.

0 comments on commit e49c66b

Please sign in to comment.