[DevTools] Enable Suspense tab by default (#35768)

This commit is contained in:
Sebastian "Sebbie" Silbermann
2026-02-12 16:50:29 +01:00
committed by GitHub
parent 8374c2abf1
commit 705055d7ac
5 changed files with 12 additions and 59 deletions

View File

@@ -167,10 +167,6 @@ function createBridgeAndStore() {
supportsClickToInspect: true,
});
store.addListener('enableSuspenseTab', () => {
createSuspensePanel();
});
store.addListener('settingsUpdated', (hookSettings, componentFilters) => {
chrome.storage.local.set({...hookSettings, componentFilters});
});
@@ -565,8 +561,7 @@ function mountReactDevTools() {
createProfilerPanel();
createSourcesEditorPanel();
createElementsInspectPanel();
// Suspense Tab is created via the hook
// TODO(enableSuspenseTab): Create eagerly once Suspense tab is stable
createSuspensePanel();
}
let reactPollingInstance = null;

View File

@@ -38,7 +38,7 @@ import type {
ElementType,
} from 'react-devtools-shared/src/frontend/types';
import type {GroupItem} from './views/TraceUpdates/canvas';
import {gte, isReactNativeEnvironment} from './utils';
import {isReactNativeEnvironment} from './utils';
import {
sessionStorageGetItem,
sessionStorageRemoveItem,
@@ -961,16 +961,6 @@ export default class Agent extends EventEmitter<{
rendererInterface.setTraceUpdatesEnabled(this._traceUpdatesEnabled);
const renderer = rendererInterface.renderer;
if (renderer !== null) {
const devRenderer = renderer.bundleType === 1;
const enableSuspenseTab =
devRenderer && gte(renderer.version, '19.3.0-canary');
if (enableSuspenseTab) {
this._bridge.send('enableSuspenseTab');
}
}
// When the renderer is attached, we need to tell it whether
// we remember the previous selection that we'd like to restore.
// It'll start tracking mounts for matches to the last selection path.

View File

@@ -199,7 +199,6 @@ export type BackendEvents = {
backendInitialized: [],
backendVersion: [string],
bridgeProtocol: [BridgeProtocol],
enableSuspenseTab: [],
extensionBackendInitialized: [],
fastRefreshScheduled: [],
getSavedPreferences: [],

View File

@@ -143,7 +143,6 @@ export default class Store extends EventEmitter<{
backendVersion: [],
collapseNodesByDefault: [],
componentFilters: [],
enableSuspenseTab: [],
error: [Error],
hookSettings: [$ReadOnly<DevToolsHookSettings>],
hostInstanceSelected: [Element['id'] | null],
@@ -239,8 +238,6 @@ export default class Store extends EventEmitter<{
_supportsClickToInspect: boolean = false;
_supportsTimeline: boolean = false;
_supportsTraceUpdates: boolean = false;
// Dynamically set if the renderer supports the Suspense tab.
_supportsSuspenseTab: boolean = false;
_isReloadAndProfileFrontendSupported: boolean = false;
_isReloadAndProfileBackendSupported: boolean = false;
@@ -341,7 +338,6 @@ export default class Store extends EventEmitter<{
bridge.addListener('hookSettings', this.onHookSettings);
bridge.addListener('backendInitialized', this.onBackendInitialized);
bridge.addListener('selectElement', this.onHostInstanceSelected);
bridge.addListener('enableSuspenseTab', this.onEnableSuspenseTab);
}
// This is only used in tests to avoid memory leaks.
@@ -2394,15 +2390,6 @@ export default class Store extends EventEmitter<{
}
}
get supportsSuspenseTab(): boolean {
return this._supportsSuspenseTab;
}
onEnableSuspenseTab = (): void => {
this._supportsSuspenseTab = true;
this.emit('enableSuspenseTab');
};
// The Store should never throw an Error without also emitting an event.
// Otherwise Store errors will be invisible to users,
// but the downstream errors they cause will be reported as bugs.

View File

@@ -135,21 +135,7 @@ const suspenseTab = {
title: 'React Suspense',
};
const defaultTabs = [componentsTab, profilerTab];
const tabsWithSuspense = [componentsTab, profilerTab, suspenseTab];
function useIsSuspenseTabEnabled(store: Store): boolean {
const subscribe = useCallback(
(onStoreChange: () => void) => {
store.addListener('enableSuspenseTab', onStoreChange);
return () => {
store.removeListener('enableSuspenseTab', onStoreChange);
};
},
[store],
);
return React.useSyncExternalStore(subscribe, () => store.supportsSuspenseTab);
}
const tabs = [componentsTab, profilerTab, suspenseTab];
export default function DevTools({
bridge,
@@ -183,8 +169,6 @@ export default function DevTools({
LOCAL_STORAGE_DEFAULT_TAB_KEY,
defaultTab,
);
const enableSuspenseTab = useIsSuspenseTabEnabled(store);
const tabs = enableSuspenseTab ? tabsWithSuspense : defaultTabs;
let tab = currentTab;
@@ -364,17 +348,15 @@ export default function DevTools({
}
/>
</div>
{enableSuspenseTab && (
<div
className={styles.TabContent}
hidden={tab !== 'suspense'}>
<SuspenseTab
portalContainer={
suspensePortalContainer
}
/>
</div>
)}
<div
className={styles.TabContent}
hidden={tab !== 'suspense'}>
<SuspenseTab
portalContainer={
suspensePortalContainer
}
/>
</div>
</div>
{editorPortalContainer ? (
<EditorPane