Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: useTransition after use gets stuck in pending state #29670

Merged
merged 2 commits into from
May 31, 2024

Conversation

acdlite
Copy link
Collaborator

@acdlite acdlite commented May 30, 2024

When a component suspends with use, we switch to the "re-render" dispatcher during the subsequent render attempt, so that we can reuse the work from the initial attempt. However, once we run out of hooks from the previous attempt, we should switch back to the regular "update" dispatcher.

This is conceptually the same fix as the one introduced in #26232. That fix only accounted for initial mount, but the useTransition regression test added in f829733 illustrates that we need to handle updates, too.

The issue affects more than just useTransition but because most of the behavior between the "re-render" and "update" dispatchers is the same it's hard to contrive other scenarios in a test, which is probably why it took so long for someone to notice.

Closes #28923 and #29209

Copy link

vercel bot commented May 30, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-compiler-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 31, 2024 9:46pm

@react-sizebot
Copy link

react-sizebot commented May 30, 2024

Comparing: ec6fe57...09f46e4

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.66 kB 6.66 kB +0.05% 1.82 kB 1.82 kB
oss-stable/react-dom/cjs/react-dom-client.production.js +0.02% 496.39 kB 496.48 kB +0.03% 88.84 kB 88.87 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.67 kB 6.67 kB +0.05% 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.02% 501.21 kB 501.30 kB +0.03% 89.54 kB 89.56 kB
facebook-www/ReactDOM-prod.classic.js +0.02% 593.88 kB 593.97 kB +0.02% 104.46 kB 104.49 kB
facebook-www/ReactDOM-prod.modern.js +0.02% 570.26 kB 570.35 kB +0.02% 100.87 kB 100.89 kB
test_utils/ReactAllWarnings.js Deleted 63.65 kB 0.00 kB Deleted 15.90 kB 0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
test_utils/ReactAllWarnings.js Deleted 63.65 kB 0.00 kB Deleted 15.90 kB 0.00 kB

Generated by 🚫 dangerJS against 09f46e4

@acdlite acdlite marked this pull request as ready for review May 30, 2024 17:15
Comment on lines 1922 to 1924
// This is a regression test. The root cause was an issue where we failed to
// switch from the "re-render" dispatcher back to the "update" dispatcher
// after a `use` suspends and triggers a replay.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it also makes sense why it didn't get stuck if we called useTransition before use. Thanks for the explainer.

// after a `use` suspends and triggers a replay.
let update;
function App({promise}) {
useState(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this testing that everything before use is still processed appropriately? May be worth a comment because right now it looks like we could remove it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was testing both and forgot to delete, I'll add another test for this one

eps1lon and others added 2 commits May 31, 2024 17:40
Introduces a regression test for a bug where the pending state of a
useTransition hook is not set back to `false` if it comes after a
`use` that suspended.

Co-authored-by: Andrew Clark <git@andrewclark.io>
When a component suspends with `use`, we switch to the "re-render"
dispatcher during the subsequent render attempt, so that we can reuse
the work from the initial attempt. However, once we run out of hooks
from the previous attempt, we should switch back to the regular
"update" dispatcher.

This is conceptually the same fix as the one introduced in facebook#26232. That
fix only accounted for initial mount, but the useTransition regression
test added in the previous commit illustrates that we need to handle
updates, too.

The issue affects more than just useTransition but because most of the
behavior between the "re-render" and "update" dispatchers is the same
it's hard to contrive other scenarios in a test, which is probably why
it took so long for someone to notice.
@acdlite acdlite merged commit adbec0c into facebook:main May 31, 2024
40 checks passed
github-actions bot pushed a commit that referenced this pull request May 31, 2024
When a component suspends with `use`, we switch to the "re-render"
dispatcher during the subsequent render attempt, so that we can reuse
the work from the initial attempt. However, once we run out of hooks
from the previous attempt, we should switch back to the regular "update"
dispatcher.

This is conceptually the same fix as the one introduced in
#26232. That fix only accounted
for initial mount, but the useTransition regression test added in
f829733 illustrates that we need to
handle updates, too.

The issue affects more than just useTransition but because most of the
behavior between the "re-render" and "update" dispatchers is the same
it's hard to contrive other scenarios in a test, which is probably why
it took so long for someone to notice.

Closes #28923 and #29209

---------

Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>

DiffTrain build for [adbec0c](adbec0c)
github-actions bot pushed a commit that referenced this pull request May 31, 2024
When a component suspends with `use`, we switch to the "re-render"
dispatcher during the subsequent render attempt, so that we can reuse
the work from the initial attempt. However, once we run out of hooks
from the previous attempt, we should switch back to the regular "update"
dispatcher.

This is conceptually the same fix as the one introduced in
#26232. That fix only accounted
for initial mount, but the useTransition regression test added in
f829733 illustrates that we need to
handle updates, too.

The issue affects more than just useTransition but because most of the
behavior between the "re-render" and "update" dispatchers is the same
it's hard to contrive other scenarios in a test, which is probably why
it took so long for someone to notice.

Closes #28923 and #29209

---------

Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>

DiffTrain build for commit adbec0c.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[React 19] useTransition()'s pending state does not go back to false (revision 94eed63c49-20240425)
4 participants