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: Update while suspended fails to interrupt #26739

Merged

Conversation

acdlite
Copy link
Collaborator

@acdlite acdlite commented Apr 28, 2023

This fixes a bug with use where if you update a component that's currently suspended, React will sometimes mistake it for a render phase update.

This happens because we don't reset currentlyRenderingFiber until the suspended is unwound. And with use, that can happen asynchronously, most commonly when the work loop is suspended during a transition.

The fix is to make sure currentlyRenderingFiber is only set when we're in the middle of rendering, which used to be true until use was introduced.

More specifically this means clearing currentlyRenderingFiber when something throws and setting it again when we resume work.

In many cases, this bug will fail "gracefully" because the update is still added to the queue; it's not dropped completely. It's also somewhat rare because it has to be the exact same component that's currently suspended. But it's still a bug. I wrote a regression test that shows a sync update failing to interrupt a suspended component.

This demonstrates a bug with `use` where if you update a component
that's currently suspended, React will sometimes mistake it for a
render phase update.

This happens because we don't reset `currentlyRenderingFiber` until the
suspended is unwound. And with `use`, that can happen asynchronously,
most commonly when the work loop is suspended during a transition.

The fix is to make sure `currentlyRenderingFiber` is only set when
we're in the middle of rendering, which used to be true until `use`
was introduced.

More specifically this means clearing `currentlyRenderingFiber` when
something throws and setting it again when we resume work.

In many cases, this bug will fail "gracefully" because the update is
still added to the queue; it's not dropped completely. It's also
somewhat rare because it has to be the exact same compone that's
currently suspended. But it's still a bug. I wrote a regression test
that shows a sync update failing to interrupt a suspended component.
@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 28, 2023
@react-sizebot
Copy link

react-sizebot commented Apr 28, 2023

Comparing: 540bab0...f0322ed

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 = 164.02 kB 164.04 kB +0.02% 51.71 kB 51.72 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 170.32 kB 170.34 kB +0.01% 53.62 kB 53.63 kB
facebook-www/ReactDOM-prod.classic.js +0.04% 566.81 kB 567.04 kB +0.03% 100.13 kB 100.16 kB
facebook-www/ReactDOM-prod.modern.js +0.04% 550.55 kB 550.78 kB +0.03% 97.33 kB 97.36 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against f0322ed

@acdlite acdlite force-pushed the fix-update-while-suspended-fails-to-interrupt branch from eab4cb5 to f0322ed Compare April 28, 2023 19:28
@acdlite acdlite merged commit 18282f8 into facebook:main Apr 28, 2023
acdlite added a commit to acdlite/next.js that referenced this pull request May 3, 2023
Includes the following upstream changes:

- [5dd90c562](https://github.com/facebook/react/commits/5dd90c562) Use content hash for react-native builds ([vercel#26734](facebook/react#26734)) (Samuel Susla)
- [559e83aeb](https://github.com/facebook/react/commits/559e83aeb) [Fizz] Allow an action provide a custom set of props to use for progressive enhancement ([vercel#26749](facebook/react#26749)) (Sebastian Markbåge)
- [67f4fb021](https://github.com/facebook/react/commits/67f4fb021) Allow forms to skip hydration of hidden inputs ([vercel#26735](facebook/react#26735)) (Sebastian Markbåge)
- [8ea96ef84](https://github.com/facebook/react/commits/8ea96ef84) [Fizz] Encode external fizz runtime into chunks eagerly ([vercel#26752](facebook/react#26752)) (Josh Story)
- [491aec5d6](https://github.com/facebook/react/commits/491aec5d6) Implement experimental_useOptimisticState ([vercel#26740](facebook/react#26740)) (Andrew Clark)
- [9545e4810](https://github.com/facebook/react/commits/9545e4810) Add nonce support to bootstrap scripts and external runtime ([vercel#26738](facebook/react#26738)) (Dan Ott)
- [86b0e9199](https://github.com/facebook/react/commits/86b0e9199) Gate DevTools test to fix CI ([#26742](facebook/react#26742)) (Andrew Clark)
- [b12bea62d](https://github.com/facebook/react/commits/b12bea62d) Preinits should support a nonce option ([#26744](facebook/react#26744)) (Josh Story)
- [efbd68511](https://github.com/facebook/react/commits/efbd68511) Remove unused `initialStatus` parameter from `useHostTransitionStatus` ([vercel#26743](facebook/react#26743)) (Sebastian Silbermann)
- [18282f881](https://github.com/facebook/react/commits/18282f881) Fix: Update while suspended fails to interrupt ([vercel#26739](facebook/react#26739)) (Andrew Clark)
- [540bab085](https://github.com/facebook/react/commits/540bab085) Implement experimental_useFormStatus ([#26722](facebook/react#26722)) (Andrew Clark)
acdlite added a commit to acdlite/next.js that referenced this pull request May 3, 2023
Includes the following upstream changes:

- [5dd90c562](https://github.com/facebook/react/commits/5dd90c562) Use content hash for react-native builds ([vercel#26734](facebook/react#26734)) (Samuel Susla)
- [559e83aeb](https://github.com/facebook/react/commits/559e83aeb) [Fizz] Allow an action provide a custom set of props to use for progressive enhancement ([vercel#26749](facebook/react#26749)) (Sebastian Markbåge)
- [67f4fb021](https://github.com/facebook/react/commits/67f4fb021) Allow forms to skip hydration of hidden inputs ([vercel#26735](facebook/react#26735)) (Sebastian Markbåge)
- [8ea96ef84](https://github.com/facebook/react/commits/8ea96ef84) [Fizz] Encode external fizz runtime into chunks eagerly ([vercel#26752](facebook/react#26752)) (Josh Story)
- [491aec5d6](https://github.com/facebook/react/commits/491aec5d6) Implement experimental_useOptimisticState ([vercel#26740](facebook/react#26740)) (Andrew Clark)
- [9545e4810](https://github.com/facebook/react/commits/9545e4810) Add nonce support to bootstrap scripts and external runtime ([vercel#26738](facebook/react#26738)) (Dan Ott)
- [86b0e9199](https://github.com/facebook/react/commits/86b0e9199) Gate DevTools test to fix CI ([#26742](facebook/react#26742)) (Andrew Clark)
- [b12bea62d](https://github.com/facebook/react/commits/b12bea62d) Preinits should support a nonce option ([#26744](facebook/react#26744)) (Josh Story)
- [efbd68511](https://github.com/facebook/react/commits/efbd68511) Remove unused `initialStatus` parameter from `useHostTransitionStatus` ([vercel#26743](facebook/react#26743)) (Sebastian Silbermann)
- [18282f881](https://github.com/facebook/react/commits/18282f881) Fix: Update while suspended fails to interrupt ([vercel#26739](facebook/react#26739)) (Andrew Clark)
- [540bab085](https://github.com/facebook/react/commits/540bab085) Implement experimental_useFormStatus ([#26722](facebook/react#26722)) (Andrew Clark)
ijjk pushed a commit to vercel/next.js that referenced this pull request May 3, 2023
Includes the following upstream changes:

- [b7972822b](https://github.com/facebook/react/commits/b7972822b)
useOptimisticState -> useOptimistic
([#26772](facebook/react#26772)) (Andrew Clark)
- [388686f29](https://github.com/facebook/react/commits/388686f29) Add
"canary" to list of allowed npm dist tags
([#26767](facebook/react#26767)) (Andrew Clark)
- [8a25302c6](https://github.com/facebook/react/commits/8a25302c6)
fix[dynamic-scripts-injection]: unregister content scripts before
registration ([#26765](facebook/react#26765))
(Ruslan Lesiutin)
- [2c2476834](https://github.com/facebook/react/commits/2c2476834)
Rename "next" prerelease channel to "canary"
([#26761](facebook/react#26761)) (Andrew Clark)
- [fa4314841](https://github.com/facebook/react/commits/fa4314841)
Remove deprecated workflow key from Circle config
([#26762](facebook/react#26762)) (Andrew Clark)
- [5dd90c562](https://github.com/facebook/react/commits/5dd90c562) Use
content hash for react-native builds
([#26734](facebook/react#26734)) (Samuel Susla)
- [559e83aeb](https://github.com/facebook/react/commits/559e83aeb)
[Fizz] Allow an action provide a custom set of props to use for
progressive enhancement
([#26749](facebook/react#26749)) (Sebastian
Markbåge)
- [67f4fb021](https://github.com/facebook/react/commits/67f4fb021) Allow
forms to skip hydration of hidden inputs
([#26735](facebook/react#26735)) (Sebastian
Markbåge)
- [8ea96ef84](https://github.com/facebook/react/commits/8ea96ef84)
[Fizz] Encode external fizz runtime into chunks eagerly
([#26752](facebook/react#26752)) (Josh Story)
- [491aec5d6](https://github.com/facebook/react/commits/491aec5d6)
Implement experimental_useOptimisticState
([#26740](facebook/react#26740)) (Andrew Clark)
- [9545e4810](https://github.com/facebook/react/commits/9545e4810) Add
nonce support to bootstrap scripts and external runtime
([#26738](facebook/react#26738)) (Dan Ott)
- [86b0e9199](https://github.com/facebook/react/commits/86b0e9199) Gate
DevTools test to fix CI
([#26742](facebook/react#26742)) (Andrew Clark)
- [b12bea62d](https://github.com/facebook/react/commits/b12bea62d)
Preinits should support a nonce option
([#26744](facebook/react#26744)) (Josh Story)
- [efbd68511](https://github.com/facebook/react/commits/efbd68511)
Remove unused `initialStatus` parameter from `useHostTransitionStatus`
([#26743](facebook/react#26743)) (Sebastian
Silbermann)
- [18282f881](https://github.com/facebook/react/commits/18282f881) Fix:
Update while suspended fails to interrupt
([#26739](facebook/react#26739)) (Andrew Clark)
- [540bab085](https://github.com/facebook/react/commits/540bab085)
Implement experimental_useFormStatus
([#26722](facebook/react#26722)) (Andrew Clark)

---------
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This fixes a bug with `use` where if you update a component that's
currently suspended, React will sometimes mistake it for a render phase
update.

This happens because we don't reset `currentlyRenderingFiber` until the
suspended is unwound. And with `use`, that can happen asynchronously,
most commonly when the work loop is suspended during a transition.

The fix is to make sure `currentlyRenderingFiber` is only set when we're
in the middle of rendering, which used to be true until `use` was
introduced.

More specifically this means clearing `currentlyRenderingFiber` when
something throws and setting it again when we resume work.

In many cases, this bug will fail "gracefully" because the update is
still added to the queue; it's not dropped completely. It's also
somewhat rare because it has to be the exact same component that's
currently suspended. But it's still a bug. I wrote a regression test
that shows a sync update failing to interrupt a suspended component.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This fixes a bug with `use` where if you update a component that's
currently suspended, React will sometimes mistake it for a render phase
update.

This happens because we don't reset `currentlyRenderingFiber` until the
suspended is unwound. And with `use`, that can happen asynchronously,
most commonly when the work loop is suspended during a transition.

The fix is to make sure `currentlyRenderingFiber` is only set when we're
in the middle of rendering, which used to be true until `use` was
introduced.

More specifically this means clearing `currentlyRenderingFiber` when
something throws and setting it again when we resume work.

In many cases, this bug will fail "gracefully" because the update is
still added to the queue; it's not dropped completely. It's also
somewhat rare because it has to be the exact same component that's
currently suspended. But it's still a bug. I wrote a regression test
that shows a sync update failing to interrupt a suspended component.

DiffTrain build for commit 18282f8.
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.

4 participants