diff --git a/packages/react-devtools-shared/src/__tests__/treeContext-test.js b/packages/react-devtools-shared/src/__tests__/treeContext-test.js index 0db248c017861..30d21c0335ddb 100644 --- a/packages/react-devtools-shared/src/__tests__/treeContext-test.js +++ b/packages/react-devtools-shared/src/__tests__/treeContext-test.js @@ -2119,6 +2119,64 @@ describe('TreeListContext', () => { `); }); + it('should update correctly when elements are added/removed', () => { + const container = document.createElement('div'); + let errored = false; + function ErrorOnce() { + if (!errored) { + errored = true; + console.error('test-only:one-time-error'); + } + return null; + } + withErrorsOrWarningsIgnored(['test-only:'], () => + utils.act(() => + legacyRender( + + + , + container, + ), + ), + ); + + let renderer; + utils.act(() => (renderer = TestRenderer.create())); + expect(state).toMatchInlineSnapshot(` + ✕ 1, ⚠ 0 + [root] + ✕ + `); + + withErrorsOrWarningsIgnored(['test-only:'], () => + utils.act(() => + legacyRender( + + + + , + container, + ), + ), + ); + + utils.act(() => renderer.update()); + expect(state).toMatchInlineSnapshot(` + ✕ 1, ⚠ 0 + [root] + + ✕ + `); + + selectNextErrorOrWarning(); + expect(state).toMatchInlineSnapshot(` + ✕ 1, ⚠ 0 + [root] + + → ✕ + `); + }); + it('should update select and auto-expand parts components within hidden parts of the tree', () => { const Wrapper = ({children}) => children; diff --git a/packages/react-devtools-shared/src/devtools/store.js b/packages/react-devtools-shared/src/devtools/store.js index 16bc56ae64f07..7cd5c41e8b0d7 100644 --- a/packages/react-devtools-shared/src/devtools/store.js +++ b/packages/react-devtools-shared/src/devtools/store.js @@ -1187,6 +1187,18 @@ export default class Store extends EventEmitter<{| console.groupEnd(); } + const indicesOfCachedErrorsOrWarningsAreStale = + !haveErrorsOrWarningsChanged && + (addedElementIDs.length > 0 || removedElementIDs.size > 0); + if (indicesOfCachedErrorsOrWarningsAreStale) { + this._cachedErrorAndWarningTuples.forEach(entry => { + const index = this.getIndexOfElementID(entry.id); + if (index !== null) { + entry.index = index; + } + }); + } + this.emit('mutated', [addedElementIDs, removedElementIDs]); };