Skip to content

Commit

Permalink
Batch async actions even if useTransition is unmounted (#28078)
Browse files Browse the repository at this point in the history
If there are multiple updates inside an async action, they should all be
rendered in the same batch, even if they are separate by an async
operation (`await`). We currently implement this by suspending in the
`useTransition` hook to block the update from committing until all
possible updates have been scheduled by the action. The reason we did it
this way is so you can "cancel" an action by navigating away from the UI
that triggered it.

The problem with that approach, though, is that even if you navigate
away from the `useTransition` hook, the action may have updated shared
parts of the UI that are still in the tree. So we may need to continue
suspending even after the `useTransition` hook is deleted.

In other words, the lifetime of an async action scope is longer than the
lifetime of a particular `useTransition` hook.

The solution is to suspend whenever _any_ update that is part of the
async action scope is unwrapped during render. So, inside useState and
useReducer.

This fixes a related issue where an optimistic update is reverted before
the async action has finished, because we were relying on the
`useTransition` hook to prevent the optimistic update from finishing.

This also prepares us to support async actions being passed to the
non-hook form of `startTransition` (though this isn't implemented yet).

DiffTrain build for commit 11c9fd0.
  • Loading branch information
acdlite committed Jan 25, 2024
1 parent 95c2763 commit 5b6d492
Show file tree
Hide file tree
Showing 13 changed files with 12,952 additions and 12,771 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if (__DEV__) {
) {
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
}
var ReactVersion = "18.3.0-canary-2efb14260-20240124";
var ReactVersion = "18.3.0-canary-11c9fd0c5-20240124";

// ATTENTION
// When adding new symbols to this file,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,4 +539,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-canary-2efb14260-20240124";
exports.version = "18.3.0-canary-11c9fd0c5-20240124";
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-canary-2efb14260-20240124";
exports.version = "18.3.0-canary-11c9fd0c5-20240124";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2efb1426067322cdb08304432b3ac849dee52bd9
11c9fd0c53133f24f5270d36591b65b8fc2ebd25
Loading

0 comments on commit 5b6d492

Please sign in to comment.