Skip to content

Commit a299ba0

Browse files
committed
Deprecate throw-a-Promise
1 parent b666db1 commit a299ba0

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
'use strict';
22

33
module.exports = function shouldIgnoreConsoleWarn(format) {
4+
if (
5+
typeof format === 'string' &&
6+
format.startsWith(
7+
'Throwing a Promise to cause it to suspend is deprecated in React',
8+
)
9+
) {
10+
return true;
11+
}
412
return false;
513
};

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,8 @@ function resetSuspendedWorkLoopOnUnwind(fiber: Fiber) {
20132013
resetChildReconcilerOnUnwind();
20142014
}
20152015

2016+
let didWarnForThrowAPromise = false;
2017+
20162018
function handleThrow(root: FiberRoot, thrownValue: any): void {
20172019
// A component threw an exception. Usually this is because it suspended, but
20182020
// it also includes regular program errors.
@@ -2066,19 +2068,34 @@ function handleThrow(root: FiberRoot, thrownValue: any): void {
20662068
// case where we think this should happen.
20672069
workInProgressSuspendedReason = SuspendedOnHydration;
20682070
} else {
2069-
// This is a regular error.
20702071
const isWakeable =
20712072
thrownValue !== null &&
20722073
typeof thrownValue === 'object' &&
20732074
typeof thrownValue.then === 'function';
2074-
2075-
workInProgressSuspendedReason = isWakeable
2076-
? // A wakeable object was thrown by a legacy Suspense implementation.
2077-
// This has slightly different behavior than suspending with `use`.
2078-
SuspendedOnDeprecatedThrowPromise
2079-
: // This is a regular error. If something earlier in the component already
2080-
// suspended, we must clear the thenable state to unblock the work loop.
2081-
SuspendedOnError;
2075+
if (isWakeable) {
2076+
// A wakeable object was thrown by a legacy Suspense implementation.
2077+
// This has slightly different behavior than suspending with `use`.
2078+
workInProgressSuspendedReason = SuspendedOnDeprecatedThrowPromise;
2079+
if (__DEV__) {
2080+
if (!didWarnForThrowAPromise && workInProgress !== null) {
2081+
didWarnForThrowAPromise = true;
2082+
const componentName =
2083+
getComponentNameFromFiber(workInProgress) || 'unknown';
2084+
runWithFiberInDEV(workInProgress, () => {
2085+
console.warn(
2086+
'Throwing a Promise to cause it to suspend is deprecated in React.\n' +
2087+
'Please update your library to call use(promise) instead.\n' +
2088+
'See https://react.dev/reference/react/use\n\n in %s',
2089+
componentName,
2090+
);
2091+
});
2092+
}
2093+
}
2094+
} else {
2095+
// This is a regular error. If something earlier in the component already
2096+
// suspended, we must clear the thenable state to unblock the work loop.
2097+
workInProgressSuspendedReason = SuspendedOnError;
2098+
}
20822099
}
20832100

20842101
workInProgressThrownValue = thrownValue;

0 commit comments

Comments
 (0)