Skip to content

Commit ba6590d

Browse files
authored
[DevTools] Rerender boundaries when they unsuspend when advancing the timeline (facebook#34359)
1 parent 2710795 commit ba6590d

File tree

3 files changed

+51
-18
lines changed

3 files changed

+51
-18
lines changed

packages/react-devtools-shared/src/__tests__/store-test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,34 @@ describe('Store', () => {
987987
<Suspense name="two" rects={[{x:1,y:2,width:5,height:1}]}>
988988
<Suspense name="three" rects={[{x:1,y:2,width:5,height:1}]}>
989989
`);
990+
991+
await actAsync(() => {
992+
agent.overrideSuspenseMilestone({
993+
rendererID,
994+
rootID,
995+
suspendedSet: [],
996+
});
997+
});
998+
999+
expect(store).toMatchInlineSnapshot(`
1000+
[root]
1001+
▾ <App>
1002+
<Component key="Outside">
1003+
▾ <Suspense name="parent">
1004+
<Component key="Unrelated at Start">
1005+
▾ <Suspense name="one">
1006+
<Component key="Suspense 1 Content">
1007+
▾ <Suspense name="two">
1008+
<Component key="Suspense 2 Content">
1009+
▾ <Suspense name="three">
1010+
<Component key="Suspense 3 Content">
1011+
<Component key="Unrelated at End">
1012+
[shell]
1013+
<Suspense name="parent" rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}>
1014+
<Suspense name="one" rects={[{x:1,y:2,width:5,height:1}]}>
1015+
<Suspense name="two" rects={[{x:1,y:2,width:5,height:1}]}>
1016+
<Suspense name="three" rects={[{x:1,y:2,width:5,height:1}]}>
1017+
`);
9901018
});
9911019

9921020
it('should display a partially rendered SuspenseList', async () => {

packages/react-devtools-shared/src/backend/fiber/renderer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7519,6 +7519,9 @@ export function attach(
75197519
}
75207520
75217521
// TODO: Allow overriding the timeline for the specified root.
7522+
forceFallbackForFibers.forEach(fiber => {
7523+
scheduleUpdate(fiber);
7524+
});
75227525
forceFallbackForFibers.clear();
75237526
75247527
for (let i = 0; i < suspendedSet.length; ++i) {

packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTimeline.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -126,26 +126,28 @@ function SuspenseTimelineInput({rootID}: {rootID: Element['id'] | void}) {
126126
}
127127

128128
function handleChange(event: SyntheticEvent) {
129-
const pendingValue = +event.currentTarget.value;
130-
for (let i = 0; i < timeline.length; i++) {
131-
const forceFallback = i > pendingValue;
132-
const suspense = timeline[i];
133-
const elementID = suspense.id;
134-
const rendererID = store.getRendererIDForElement(elementID);
135-
if (rendererID === null) {
136-
// TODO: Handle disconnected elements.
137-
console.warn(
138-
`No renderer ID found for element ${elementID} in suspense timeline.`,
139-
);
140-
} else {
141-
bridge.send('overrideSuspense', {
142-
id: elementID,
143-
rendererID,
144-
forceFallback,
145-
});
146-
}
129+
if (rootID === undefined) {
130+
return;
131+
}
132+
const rendererID = store.getRendererIDForElement(rootID);
133+
if (rendererID === null) {
134+
console.error(
135+
`No renderer ID found for root element ${rootID} in suspense timeline.`,
136+
);
137+
return;
147138
}
148139

140+
const pendingValue = +event.currentTarget.value;
141+
const suspendedSet = timeline
142+
.slice(pendingValue + 1)
143+
.map(suspense => suspense.id);
144+
145+
bridge.send('overrideSuspenseMilestone', {
146+
rendererID,
147+
rootID,
148+
suspendedSet,
149+
});
150+
149151
const suspense = timeline[pendingValue];
150152
const elementID = suspense.id;
151153
highlightHostInstance(elementID);

0 commit comments

Comments
 (0)