Skip to content

Commit 01c4d03

Browse files
authored
[DevTools] Clear element inspection if host element not owned by any renderer is selected (facebook#35504)
1 parent cbc4d40 commit 01c4d03

File tree

5 files changed

+28
-14
lines changed

5 files changed

+28
-14
lines changed

packages/react-devtools-extensions/src/main/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ function createElementsInspectPanel() {
330330
inspectedElementPortalContainer = portal.container;
331331
if (inspectedElementPortalContainer != null && render) {
332332
ensureInitialHTMLIsCleared(inspectedElementPortalContainer);
333+
bridge.send('syncSelectionFromBuiltinElementsPanel');
333334

334335
render();
335336
portal.injectStyles(cloneStyleTags);

packages/react-devtools-shared/src/backend/agent.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -938,11 +938,19 @@ export default class Agent extends EventEmitter<{
938938
}
939939
};
940940

941-
selectNode(target: HostInstance): void {
942-
const match = this.getIDForHostInstance(target);
943-
if (match !== null) {
944-
this._bridge.send('selectElement', match.id);
945-
}
941+
selectNode(target: HostInstance | null): void {
942+
const match = target !== null ? this.getIDForHostInstance(target) : null;
943+
this._bridge.send(
944+
'selectElement',
945+
match !== null
946+
? match.id
947+
: // If you click outside a React root in the Elements panel, we want to give
948+
// feedback that no selection is possible so we clear the selection.
949+
// Otherwise clicking outside a React root is indistinguishable from clicking
950+
// a different host node that leads to the same selected React element
951+
// due to Component filters
952+
null,
953+
);
946954
}
947955

948956
registerRendererInterface(
@@ -988,10 +996,7 @@ export default class Agent extends EventEmitter<{
988996

989997
syncSelectionFromBuiltinElementsPanel: () => void = () => {
990998
const target = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0;
991-
if (target == null) {
992-
return;
993-
}
994-
this.selectNode(target);
999+
this.selectNode(target == null ? null : target);
9951000
};
9961001

9971002
shutdown: () => void = () => {

packages/react-devtools-shared/src/bridge.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ export type BackendEvents = {
214214
profilingStatus: [boolean],
215215
reloadAppForProfiling: [],
216216
saveToClipboard: [string],
217-
selectElement: [number],
217+
selectElement: [number | null],
218218
shutdown: [],
219219
stopInspectingHost: [boolean],
220220
scrollTo: [{left: number, top: number, right: number, bottom: number}],

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export default class Store extends EventEmitter<{
147147
enableSuspenseTab: [],
148148
error: [Error],
149149
hookSettings: [$ReadOnly<DevToolsHookSettings>],
150-
hostInstanceSelected: [Element['id']],
150+
hostInstanceSelected: [Element['id'] | null],
151151
settingsUpdated: [$ReadOnly<DevToolsHookSettings>],
152152
mutated: [
153153
[
@@ -2381,8 +2381,15 @@ export default class Store extends EventEmitter<{
23812381
this._bridge.send('getHookSettings'); // Warm up cached hook settings
23822382
};
23832383

2384-
onHostInstanceSelected: (elementId: number) => void = elementId => {
2385-
if (this._lastSelectedHostInstanceElementId === elementId) {
2384+
onHostInstanceSelected: (elementId: number | null) => void = elementId => {
2385+
if (
2386+
this._lastSelectedHostInstanceElementId === elementId &&
2387+
// Force clear selection e.g. when we inspect an element in the Components panel
2388+
// and then switch to the browser's Elements panel.
2389+
// We wouldn't want to stay on the inspected element if we're inspecting
2390+
// an element not owned by React when switching to the browser's Elements panel.
2391+
elementId !== null
2392+
) {
23862393
return;
23872394
}
23882395

packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,8 +967,9 @@ function TreeContextController({
967967

968968
// Listen for host element selections.
969969
useEffect(() => {
970-
const handler = (id: Element['id']) =>
970+
const handler = (id: Element['id'] | null) => {
971971
transitionDispatch({type: 'SELECT_ELEMENT_BY_ID', payload: id});
972+
};
972973

973974
store.addListener('hostInstanceSelected', handler);
974975
return () => store.removeListener('hostInstanceSelected', handler);

0 commit comments

Comments
 (0)