[DevTools] Fix Suspense boundaries always being marked as not suspended (#34206)
Sebastian "Sebbie" Silbermann committed
Aug 15, 2025 at 19:39 UTC
2d98b45d92ee9adc5ec6dbd2a5a270e0fd2607a4
7 files changed
+17
-4
packages/react-devtools-shared/src/backend/fiber/renderer.js
+8
@@ -6071,6 +6071,11 @@ export function attach(
6071
nativeTag = getNativeTag(fiber.stateNode);
6072
}
6073
6074
+ let isSuspended: boolean | null = null;
6075
+ if (tag === SuspenseComponent) {
6076
+ isSuspended = memoizedState !== null;
6077
+ }
6078
+
6079
const suspendedBy =
6080
fiberInstance.suspenseNode !== null
6081
? // If this is a Suspense boundary, then we include everything in the subtree that might suspend
@@ -6121,6 +6126,7 @@ export function attach(
6126
forceFallbackForFibers.has(fiber) ||
6127
(fiber.alternate !== null &&
6128
forceFallbackForFibers.has(fiber.alternate))),
6129
+ isSuspended: isSuspended,
6130
6131
source,
6132
@@ -6209,6 +6215,7 @@ export function attach(
6215
const componentLogsEntry =
6216
componentInfoToComponentLogsMap.get(componentInfo);
6217
6218
+ const isSuspended = null;
6219
// Things that Suspended this Server Component (use(), awaits and direct child promises)
6220
const suspendedBy = virtualInstance.suspendedBy;
6221
const suspendedByRange = getSuspendedByRange(
@@ -6230,6 +6237,7 @@ export function attach(
6237
isErrored: false,
6238
6239
canToggleSuspense: supportsTogglingSuspense && hasSuspenseBoundary,
6240
+ isSuspended: isSuspended,
6241
6242
source,
6243
packages/react-devtools-shared/src/backend/legacy/renderer.js
+1
@@ -836,6 +836,7 @@ export function attach(
836
837
// Suspense did not exist in legacy versions
838
canToggleSuspense: false,
839
+ isSuspended: null,
840
841
source: null,
842
packages/react-devtools-shared/src/backend/types.js
+2
@@ -285,6 +285,8 @@ export type InspectedElement = {
285
286
// Is this Suspense, and can its value be overridden now?
287
canToggleSuspense: boolean,
288
+ // If this Element is suspended. Currently only set on Suspense boundaries.
289
+ isSuspended: boolean | null,
290
291
// Does the component have legacy context attached to it.
292
hasLegacyContext: boolean,
packages/react-devtools-shared/src/backendAPI.js
+2
@@ -251,6 +251,7 @@ export function convertInspectedElementBackendToFrontend(
251
canToggleError,
252
isErrored,
253
canToggleSuspense,
254
+ isSuspended,
255
hasLegacyContext,
256
id,
257
type,
@@ -287,6 +288,7 @@ export function convertInspectedElementBackendToFrontend(
288
canToggleError,
289
isErrored,
290
canToggleSuspense,
291
+ isSuspended,
292
hasLegacyContext,
293
id,
294
key,
packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js
+1
-1
@@ -113,7 +113,7 @@ export default function InspectedElementWrapper(_: Props): React.Node {
113
element !== null &&
114
element.type === ElementTypeSuspense &&
115
inspectedElement != null &&
116
- inspectedElement.state != null;
116
+ inspectedElement.isSuspended;
117
118
const canToggleError =
119
!hideToggleErrorAction &&
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspenseToggle.js
+1
-3
@@ -30,15 +30,13 @@ export default function InspectedElementSuspenseToggle({
30
}: Props): React.Node {
31
const {readOnly} = React.useContext(OptionsContext);
32
33
- const {id, state, type} = inspectedElement;
33
+ const {id, isSuspended, type} = inspectedElement;
34
const canToggleSuspense = !readOnly && inspectedElement.canToggleSuspense;
35
36
if (type !== ElementTypeSuspense) {
37
return null;
38
}
39
40
- const isSuspended = state !== null;
41
-
40
const toggleSuspense = (path: any, value: boolean) => {
41
const rendererID = store.getRendererIDForElement(id);
42
if (rendererID !== null) {
packages/react-devtools-shared/src/frontend/types.js
+2
@@ -264,6 +264,8 @@ export type InspectedElement = {
264
265
// Is this Suspense, and can its value be overridden now?
266
canToggleSuspense: boolean,
267
+ // If this Element is suspended. Currently only set on Suspense boundaries.
268
+ isSuspended: boolean | null,
269
270
// Does the component have legacy context attached to it.
271
hasLegacyContext: boolean,