[DevTools] Track whether to auto select when new timeline entries come on (#34698)
This auto updates to select the last entry in the timeline until we make the first selection. That way when new content loads in, we show the last timeline of what is visible.
Sebastian Markbåge committed
Oct 2, 2025 at 17:06 UTC
f89ed71ddf5f8cab28b202cfdc04927c683ad3cc
1 file changed
+12
-1
packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTreeContext.js
+12
-1
@@ -30,6 +30,7 @@ export type SuspenseTreeState = {
30
hoveredTimelineIndex: number | -1,
31
uniqueSuspendersOnly: boolean,
32
playing: boolean,
33
+ autoSelect: boolean,
34
};
35
36
type ACTION_SUSPENSE_TREE_MUTATION = {
@@ -123,6 +124,7 @@ function getInitialState(store: Store): SuspenseTreeState {
124
hoveredTimelineIndex: -1,
125
uniqueSuspendersOnly,
126
playing: false,
127
+ autoSelect: true,
128
};
129
130
return initialState;
@@ -181,7 +183,10 @@ function SuspenseTreeContextController({children}: Props): React.Node {
183
selectedTimelineID === null || nextTimeline.length === 0
184
? -1
185
: nextTimeline.indexOf(selectedTimelineID);
184
- if (nextTimeline.length > 0 && nextTimelineIndex === -1) {
186
+ if (
187
+ nextTimeline.length > 0 &&
188
+ (nextTimelineIndex === -1 || state.autoSelect)
189
+ ) {
190
nextTimelineIndex = nextTimeline.length - 1;
191
selectedSuspenseID = nextTimeline[nextTimelineIndex];
192
}
@@ -212,6 +217,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
217
...state,
218
selectedSuspenseID,
219
playing: false, // pause
220
+ autoSelect: false,
221
};
222
}
223
case 'SET_SUSPENSE_LINEAGE': {
@@ -223,6 +229,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
229
lineage,
230
selectedSuspenseID: suspenseID,
231
playing: false, // pause
232
+ autoSelect: false,
233
};
234
}
235
case 'SET_SUSPENSE_TIMELINE': {
@@ -277,6 +284,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
284
selectedSuspenseID: nextSelectedSuspenseID,
285
timelineIndex: nextTimelineIndex,
286
playing: false, // pause
287
+ autoSelect: false,
288
};
289
}
290
case 'SUSPENSE_SKIP_TIMELINE_INDEX': {
@@ -299,6 +307,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
307
selectedSuspenseID: nextSelectedSuspenseID,
308
timelineIndex: nextTimelineIndex,
309
playing: false, // pause
310
+ autoSelect: false,
311
};
312
}
313
case 'SUSPENSE_PLAY_PAUSE': {
@@ -325,6 +334,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
334
selectedSuspenseID: nextSelectedSuspenseID,
335
timelineIndex: nextTimelineIndex,
336
playing: mode === 'toggle' ? !state.playing : mode === 'play',
337
+ autoSelect: false,
338
};
339
}
340
case 'SUSPENSE_PLAY_TICK': {
@@ -381,6 +391,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
391
selectedSuspenseID: nextSelectedSuspenseID,
392
timelineIndex: nextTimelineIndex,
393
playing: false, // pause
394
+ autoSelect: false,
395
};
396
}
397
case 'HOVER_TIMELINE_FOR_ID': {