[DevTools] Don't call Hooks conditionally (#34644)

This commit is contained in:
Sebastian "Sebbie" Silbermann 2025-09-29 15:15:09 +02:00 committed by GitHub
parent dce1f6cd5d
commit 2bbb7be0e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 40 deletions

View File

@ -8,6 +8,7 @@
*/
import type {SchedulingEvent} from 'react-devtools-timeline/src/types';
import type {ReactFunctionLocation} from 'shared/ReactTypes';
import * as React from 'react';
import Button from '../Button';
@ -27,6 +28,28 @@ import styles from './SidebarEventInfo.css';
export type Props = {};
type FunctionLocationProps = {
location: ReactFunctionLocation,
displayName: string,
};
function FunctionLocation({location, displayName}: FunctionLocationProps) {
// TODO: We should support symbolication here as well, but
// symbolicating the whole stack can be expensive
const [canViewSource, viewSource] = useOpenResource(location, null);
return (
<li>
<Button
className={
canViewSource ? styles.ClickableSource : styles.UnclickableSource
}
disabled={!canViewSource}
onClick={viewSource}>
{displayName}
</Button>
</li>
);
}
type SchedulingEventProps = {
eventInfo: SchedulingEvent,
};
@ -74,25 +97,12 @@ function SchedulingEventInfo({eventInfo}: SchedulingEventProps) {
);
}
// TODO: We should support symbolication here as well, but
// symbolicating the whole stack can be expensive
const [canViewSource, viewSource] = useOpenResource(
location,
null,
);
return (
<li key={index}>
<Button
className={
canViewSource
? styles.ClickableSource
: styles.UnclickableSource
}
disabled={!canViewSource}
onClick={viewSource}>
{displayName}
</Button>
</li>
<FunctionLocation
key={index}
displayName={displayName}
location={location}
/>
);
},
)}

View File

@ -39,28 +39,6 @@ function SuspenseTimelineInput() {
const min = 0;
const max = timeline.length > 0 ? timeline.length - 1 : 0;
if (rootID === null) {
return (
<div className={styles.SuspenseTimelineInput}>No root selected.</div>
);
}
if (!store.supportsTogglingSuspense(rootID)) {
return (
<div className={styles.SuspenseTimelineInput}>
Can't step through Suspense in production apps.
</div>
);
}
if (timeline.length === 0) {
return (
<div className={styles.SuspenseTimelineInput}>
Root contains no Suspense nodes.
</div>
);
}
function switchSuspenseNode(nextTimelineIndex: number) {
const nextSelectedSuspenseID = timeline[nextTimelineIndex];
highlightHostInstance(nextSelectedSuspenseID);
@ -175,6 +153,28 @@ function SuspenseTimelineInput() {
};
}, [playing]);
if (rootID === null) {
return (
<div className={styles.SuspenseTimelineInput}>No root selected.</div>
);
}
if (!store.supportsTogglingSuspense(rootID)) {
return (
<div className={styles.SuspenseTimelineInput}>
Can't step through Suspense in production apps.
</div>
);
}
if (timeline.length === 0) {
return (
<div className={styles.SuspenseTimelineInput}>
Root contains no Suspense nodes.
</div>
);
}
return (
<>
<Button