Skip to content

[Fiber] Deprecate "Throw a Promise" technique#115

Open
everettbu wants to merge 1 commit into
mainfrom
deprecatethrowapromise
Open

[Fiber] Deprecate "Throw a Promise" technique#115
everettbu wants to merge 1 commit into
mainfrom
deprecatethrowapromise

Conversation

@everettbu

@everettbu everettbu commented Dec 12, 2025

Copy link
Copy Markdown

Mirror of facebook/react#34032
Original author: sebmarkbage


This has been replaced by React.use(promise) which in turn should be used unconditionally if data is depended upon.

The "throw a Promise" technique has many issues.

  • The main one is that since you can place it inside any other function, you can't easily detect what may or may not suspend. It's also easy to accidentally place a try/catch around it and treat it as an error instead. The use() syntax ensures that the lint rule warns you if you try/catch it or place it in a function that's not a Hook or Component.
  • There's no way to statically optimize the resumption of to be state machines like a generator or async await. We always have to rerender the stack.
  • The use() model can support just plain uncached Promises as well and potentially just plain async functions on the client.
  • For legacy reasons, throw-a-promise disables optimizations like yielding and resume in place (aka the Suspense optimization). That's due to the requirement to rerender from the top to avoid caches causing infinite ping loops.
  • This also has implications for visualizations since the Performance Track can no longer show the Suspended point inside the tree but have to show it as two separate renders. Other than just being slower.
  • We have no way of track the stack trace of where something suspended for debug information when it does suspend. In fact, that is even an issue with this warning itself. We cannot warn about which custom Hook threw the Promise. Just that something in this Component did.
  • Since it is only called conditionally if something isn't already in the cache, we cannot track the dependencies in Suspense DevTools since it would no longer be a dependency if it was already resolved. This isn't just an issue if it resolves before React happens to render it but it's also an issue just for plain resolves since we can't detect the difference between a new navigation that no longer depends on this data, vs the data just happened to load.
  • Finally, our implementation details have to all be written in a way to handle throwing a Promise anywhere you can throw an error including all kinds of edge case callbacks. Therefore our implementation, even for the other APIs like lazy and use(promise) are implemented similarly to share as much code as possible but it would be a lot simpler if they could just suspend in place where those APIs are implemented instead of in the core of the work loop.

@everettbu everettbu added CLA Signed React Core Team Opened by a member of the React Core Team labels Dec 12, 2025
@greptile-apps

greptile-apps Bot commented Dec 12, 2025

Copy link
Copy Markdown

Greptile Overview

Greptile Summary

Added a deprecation warning for the legacy "throw a Promise" suspense pattern. The warning fires once in development mode when a component throws a thenable object, guiding developers to use React.use(promise) instead. The test utilities were updated to suppress this expected warning during test runs.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are well-contained and follow established patterns in the codebase. The deprecation warning is properly guarded by __DEV__ and uses a module-level flag for deduplication consistent with other warnings. The test utility update correctly filters the new warning to prevent test noise.
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
packages/internal-test-utils/shouldIgnoreConsoleWarn.js 5/5 added filter to suppress new deprecation warning in tests
packages/react-reconciler/src/ReactFiberWorkLoop.js 5/5 added deprecation warning for throw-a-promise pattern in development mode

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

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.

2 participants