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

Bugfix: useDeferredValue loop during popstate transition #27559

Merged
merged 2 commits into from
Oct 21, 2023

Conversation

acdlite
Copy link
Collaborator

@acdlite acdlite commented Oct 20, 2023

During a popstate event, we attempt to render updates synchronously even if they are transitions, to preserve scroll position if possible. We do this by entangling the transition lane with the Sync lane.

However, if rendering the transition spawns additional transition updates (e.g. a setState inside useEffect), there's no reason to render those synchronously, too. We should use the normal transition behavior.

This fixes an issue where useDeferredValue during a popstate event would spawn a transition update that was itself also synchronous.

Adds a regression test where an unstable value passed to
useDeferredValue value during a popstate transition can lead to an
infinite render loop.
During a popstate event, we attempt to render updates synchronously even
if they are transitions, to preserve scroll position if possible. We
do this by entangling the transition lane with the Sync lane.

However, if rendering the transition spawns additional transition
updates (e.g. a setState inside useEffect), there's no reason to render
those synchronously, too. We should use the normal transition behavior.

This fixes an issue where useDeferredValue during a popstate event would
spawn a transition update that was itself also synchronous.
@acdlite acdlite requested review from sebmarkbage and tyao1 October 20, 2023 23:48
@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 20, 2023
@react-sizebot
Copy link

Comparing: f172fa7...c9f5737

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.min.js +0.05% 174.94 kB 175.02 kB +0.03% 54.44 kB 54.46 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js +0.05% 177.06 kB 177.15 kB +0.04% 55.12 kB 55.14 kB
facebook-www/ReactDOM-prod.classic.js +0.05% 567.28 kB 567.58 kB +0.08% 99.85 kB 99.92 kB
facebook-www/ReactDOM-prod.modern.js +0.05% 551.14 kB 551.43 kB +0.08% 96.94 kB 97.02 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against c9f5737

@sophiebits
Copy link
Collaborator

What if you update two roots in one popstate?

@acdlite
Copy link
Collaborator Author

acdlite commented Oct 21, 2023

meh it just won’t preserve scroll position

@acdlite
Copy link
Collaborator Author

acdlite commented Oct 21, 2023

We could support that but I think to do it properly we'd need to track either currentEventTransitionLane or currentPopstateTransitionEvent per root. Which we can do, but given that you're not really supposed to use multiple roots in a concurrent app anyway, because updates wouldn't be consistent, this seems fine for now.

@acdlite acdlite merged commit 6db7f42 into facebook:main Oct 21, 2023
2 checks passed
github-actions bot pushed a commit that referenced this pull request Oct 21, 2023
During a popstate event, we attempt to render updates synchronously even
if they are transitions, to preserve scroll position if possible. We do
this by entangling the transition lane with the Sync lane.

However, if rendering the transition spawns additional transition
updates (e.g. a setState inside useEffect), there's no reason to render
those synchronously, too. We should use the normal transition behavior.

This fixes an issue where useDeferredValue during a popstate event would
spawn a transition update that was itself also synchronous.

DiffTrain build for [6db7f42](6db7f42)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
)

During a popstate event, we attempt to render updates synchronously even
if they are transitions, to preserve scroll position if possible. We do
this by entangling the transition lane with the Sync lane.

However, if rendering the transition spawns additional transition
updates (e.g. a setState inside useEffect), there's no reason to render
those synchronously, too. We should use the normal transition behavior.

This fixes an issue where useDeferredValue during a popstate event would
spawn a transition update that was itself also synchronous.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
During a popstate event, we attempt to render updates synchronously even
if they are transitions, to preserve scroll position if possible. We do
this by entangling the transition lane with the Sync lane.

However, if rendering the transition spawns additional transition
updates (e.g. a setState inside useEffect), there's no reason to render
those synchronously, too. We should use the normal transition behavior.

This fixes an issue where useDeferredValue during a popstate event would
spawn a transition update that was itself also synchronous.

DiffTrain build for commit 6db7f42.
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.

5 participants