Skip to content

Commit f42ea4a

Browse files
committed
[DevTools] Wrap each tab in <Activity> if available
1 parent a2329c1 commit f42ea4a

File tree

2 files changed

+136
-92
lines changed

2 files changed

+136
-92
lines changed

packages/react-devtools-shared/src/devtools/views/DevTools.js

Lines changed: 135 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ import '@reach/menu-button/styles.css';
1313
import '@reach/tooltip/styles.css';
1414

1515
import * as React from 'react';
16-
import {useCallback, useEffect, useLayoutEffect, useMemo, useRef} from 'react';
16+
import {
17+
StrictMode,
18+
useCallback,
19+
useEffect,
20+
useLayoutEffect,
21+
useMemo,
22+
useRef,
23+
} from 'react';
1724
import Store from '../store';
1825
import {
1926
BridgeContext,
@@ -56,6 +63,38 @@ import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types';
5663
import type {ReactFunctionLocation, ReactCallSite} from 'shared/ReactTypes';
5764
import type {SourceSelection} from './Editor/EditorPane';
5865

66+
const MaybeActivity: any =
67+
React.Activity ||
68+
(React as any).unstable_Activity ||
69+
function AlwaysVisibleActivity({
70+
children,
71+
}: {
72+
children: React.Node,
73+
mode: string,
74+
}) {
75+
return children;
76+
};
77+
78+
function TabContent({
79+
children,
80+
activeTab,
81+
name,
82+
}: {
83+
children: React.Node,
84+
activeTab: string,
85+
name: string,
86+
}) {
87+
const hidden = activeTab !== name;
88+
const mode = hidden ? 'hidden' : 'visible';
89+
return (
90+
<MaybeActivity mode={mode} name={name + '-tab'}>
91+
<div className={styles.TabContent} hidden={hidden}>
92+
{children}
93+
</div>
94+
</MaybeActivity>
95+
);
96+
}
97+
5998
export type TabID = 'components' | 'profiler' | 'suspense';
6099

61100
export type ViewElementSource = (
@@ -289,6 +328,7 @@ export default function DevTools({
289328
useLayoutEffect(() => {
290329
return () => {
291330
try {
331+
// TODO: <DevTools> can't be put int <Activity> without being able to resume listening
292332
// Shut the Bridge down synchronously (during unmount).
293333
bridge.shutdown();
294334
} catch (error) {
@@ -302,98 +342,102 @@ export default function DevTools({
302342
}, []);
303343

304344
return (
305-
<BridgeContext.Provider value={bridge}>
306-
<StoreContext.Provider value={store}>
307-
<OptionsContext.Provider value={options}>
308-
<ContextMenuContext.Provider value={contextMenu}>
309-
<ModalDialogContextController>
310-
<SettingsContextController
311-
browserTheme={browserTheme}
312-
componentsPortalContainer={componentsPortalContainer}
313-
profilerPortalContainer={profilerPortalContainer}>
314-
<ViewElementSourceContext.Provider value={viewElementSource}>
315-
<HookNamesModuleLoaderContext.Provider
316-
value={hookNamesModuleLoaderFunction || null}>
317-
<FetchFileWithCachingContext.Provider
318-
value={fetchFileWithCaching || null}>
319-
<TreeContextController>
320-
<ProfilerContextController>
321-
<TimelineContextController>
322-
<InspectedElementContextController>
323-
<SuspenseTreeContextController>
324-
<ThemeProvider>
325-
<div
326-
className={styles.DevTools}
327-
ref={devToolsRef}
328-
data-react-devtools-portal-root={true}>
329-
{showTabBar && (
330-
<div className={styles.TabBar}>
331-
<ReactLogo />
332-
<span
333-
className={styles.DevToolsVersion}>
334-
{process.env.DEVTOOLS_VERSION}
335-
</span>
336-
<div className={styles.Spacer} />
337-
<TabBar
338-
currentTab={tab}
339-
id="DevTools"
340-
selectTab={selectTab}
341-
tabs={tabs}
342-
type="navigation"
343-
/>
344-
</div>
345-
)}
346-
<div
347-
className={styles.TabContent}
348-
hidden={tab !== 'components'}>
349-
<Components
350-
portalContainer={
351-
componentsPortalContainer
352-
}
353-
/>
354-
</div>
345+
<StrictMode>
346+
<BridgeContext.Provider value={bridge}>
347+
<StoreContext.Provider value={store}>
348+
<OptionsContext.Provider value={options}>
349+
<ContextMenuContext.Provider value={contextMenu}>
350+
<ModalDialogContextController>
351+
<SettingsContextController
352+
browserTheme={browserTheme}
353+
componentsPortalContainer={componentsPortalContainer}
354+
profilerPortalContainer={profilerPortalContainer}>
355+
<ViewElementSourceContext.Provider value={viewElementSource}>
356+
<HookNamesModuleLoaderContext.Provider
357+
value={hookNamesModuleLoaderFunction || null}>
358+
<FetchFileWithCachingContext.Provider
359+
value={fetchFileWithCaching || null}>
360+
<TreeContextController>
361+
<ProfilerContextController>
362+
<TimelineContextController>
363+
<InspectedElementContextController>
364+
<SuspenseTreeContextController>
365+
<ThemeProvider>
355366
<div
356-
className={styles.TabContent}
357-
hidden={tab !== 'profiler'}>
358-
<Profiler
359-
portalContainer={
360-
profilerPortalContainer
361-
}
362-
/>
367+
className={styles.DevTools}
368+
ref={devToolsRef}
369+
data-react-devtools-portal-root={true}>
370+
{showTabBar && (
371+
<div className={styles.TabBar}>
372+
<ReactLogo />
373+
<span
374+
className={styles.DevToolsVersion}>
375+
{process.env.DEVTOOLS_VERSION}
376+
</span>
377+
<div className={styles.Spacer} />
378+
<TabBar
379+
currentTab={tab}
380+
id="DevTools"
381+
selectTab={selectTab}
382+
tabs={tabs}
383+
type="navigation"
384+
/>
385+
</div>
386+
)}
387+
<TabContent
388+
name="components"
389+
activeTab={tab}>
390+
<Components
391+
portalContainer={
392+
componentsPortalContainer
393+
}
394+
/>
395+
</TabContent>
396+
<TabContent
397+
name="profiler"
398+
activeTab={tab}>
399+
<Profiler
400+
portalContainer={
401+
profilerPortalContainer
402+
}
403+
/>
404+
</TabContent>
405+
<TabContent
406+
name="suspense"
407+
activeTab={tab}>
408+
<SuspenseTab
409+
portalContainer={
410+
suspensePortalContainer
411+
}
412+
/>
413+
</TabContent>
363414
</div>
364-
<div
365-
className={styles.TabContent}
366-
hidden={tab !== 'suspense'}>
367-
<SuspenseTab
368-
portalContainer={
369-
suspensePortalContainer
370-
}
415+
{editorPortalContainer ? (
416+
<EditorPane
417+
selectedSource={currentSelectedSource}
418+
portalContainer={editorPortalContainer}
371419
/>
372-
</div>
373-
</div>
374-
{editorPortalContainer ? (
375-
<EditorPane
376-
selectedSource={currentSelectedSource}
377-
portalContainer={editorPortalContainer}
378-
/>
379-
) : null}
380-
</ThemeProvider>
381-
</SuspenseTreeContextController>
382-
</InspectedElementContextController>
383-
</TimelineContextController>
384-
</ProfilerContextController>
385-
</TreeContextController>
386-
</FetchFileWithCachingContext.Provider>
387-
</HookNamesModuleLoaderContext.Provider>
388-
</ViewElementSourceContext.Provider>
389-
</SettingsContextController>
390-
<UnsupportedBridgeProtocolDialog />
391-
{warnIfLegacyBackendDetected && <WarnIfLegacyBackendDetected />}
392-
{warnIfUnsupportedVersionDetected && <UnsupportedVersionDialog />}
393-
</ModalDialogContextController>
394-
</ContextMenuContext.Provider>
395-
</OptionsContext.Provider>
396-
</StoreContext.Provider>
397-
</BridgeContext.Provider>
420+
) : null}
421+
</ThemeProvider>
422+
</SuspenseTreeContextController>
423+
</InspectedElementContextController>
424+
</TimelineContextController>
425+
</ProfilerContextController>
426+
</TreeContextController>
427+
</FetchFileWithCachingContext.Provider>
428+
</HookNamesModuleLoaderContext.Provider>
429+
</ViewElementSourceContext.Provider>
430+
</SettingsContextController>
431+
<UnsupportedBridgeProtocolDialog />
432+
{warnIfLegacyBackendDetected && <WarnIfLegacyBackendDetected />}
433+
{warnIfUnsupportedVersionDetected && (
434+
<UnsupportedVersionDialog />
435+
)}
436+
</ModalDialogContextController>
437+
</ContextMenuContext.Provider>
438+
</OptionsContext.Provider>
439+
</StoreContext.Provider>
440+
</BridgeContext.Provider>
441+
</StrictMode>
398442
);
399443
}

packages/react-devtools-shell/src/app/InspectableElements/UseEffectEvent.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function useCustomHook() {
2828
}
2929

3030
function HookTreeCase() {
31-
const onClick = useCustomHook();
31+
const [, , onClick] = useCustomHook();
3232

3333
return <div onClick={onClick} />;
3434
}

0 commit comments

Comments
 (0)