diff --git a/src/devtools/store.js b/src/devtools/store.js index 048568d5bb..ff9129cb29 100644 --- a/src/devtools/store.js +++ b/src/devtools/store.js @@ -429,6 +429,21 @@ export default class Store extends EventEmitter { return null; } + isInsideCollapsedSubTree(id: number): boolean { + let current = this._idToElement.get(id); + while (current != null) { + if (current.parentID === 0) { + return false; + } else { + current = this._idToElement.get(current.parentID); + if (current != null && current.isCollapsed) { + return true; + } + } + } + return false; + } + startProfiling(): void { this._bridge.send('startProfiling'); diff --git a/src/devtools/views/Components/TreeContext.js b/src/devtools/views/Components/TreeContext.js index f66ad3e46e..bd295c920e 100644 --- a/src/devtools/views/Components/TreeContext.js +++ b/src/devtools/views/Components/TreeContext.js @@ -596,6 +596,20 @@ function TreeContextController({ children, viewElementSource }: Props) { state = reduceTreeState(store, state, action); state = reduceSearchState(store, state, action); state = reduceOwnersState(store, state, action); + + // If the selected ID is in a collapsed subtree, reset the selected index to null. + // We'll know the correct index after the layout effect will toggle the tree, + // and the store tree is mutated to account for that. + if ( + state.selectedElementID !== null && + store.isInsideCollapsedSubTree(state.selectedElementID) + ) { + return { + ...state, + selectedElementIndex: null, + }; + } + return state; default: throw new Error(`Unrecognized action "${type}"`);