From bc241bfcfef0fb54f6b8436bcf12c402102f565e Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 29 Apr 2016 21:52:45 +0100 Subject: [PATCH] Add getUpdateCount() to ReactComponentTreeDevtool It is necessary to exclude just mounted components from wasted calculation. --- src/isomorphic/ReactDebugTool.js | 1 + .../devtools/ReactComponentTreeDevtool.js | 10 ++++++++ .../ReactComponentTreeDevtool-test.js | 25 +++++++++++++++++++ .../ReactComponentTreeDevtool-test.native.js | 23 +++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/src/isomorphic/ReactDebugTool.js b/src/isomorphic/ReactDebugTool.js index a76668b12c..8fbc0341f8 100644 --- a/src/isomorphic/ReactDebugTool.js +++ b/src/isomorphic/ReactDebugTool.js @@ -72,6 +72,7 @@ function resetMeasurements() { tree[id] = { displayName: ReactComponentTreeDevtool.getDisplayName(id), text: ReactComponentTreeDevtool.getText(id), + updateCount: ReactComponentTreeDevtool.getUpdateCount(id), childIDs: ReactComponentTreeDevtool.getChildIDs(id), // Text nodes don't have owners but this is close enough. ownerID: ownerID || ReactComponentTreeDevtool.getOwnerID(parentID), diff --git a/src/isomorphic/devtools/ReactComponentTreeDevtool.js b/src/isomorphic/devtools/ReactComponentTreeDevtool.js index bdba5b378f..57e85b39df 100644 --- a/src/isomorphic/devtools/ReactComponentTreeDevtool.js +++ b/src/isomorphic/devtools/ReactComponentTreeDevtool.js @@ -25,6 +25,7 @@ function updateTree(id, update) { childIDs: [], displayName: 'Unknown', isMounted: false, + updateCount: 0, }; } update(tree[id]); @@ -95,6 +96,10 @@ var ReactComponentTreeDevtool = { rootIDs.push(id); }, + onUpdateComponent(id) { + updateTree(id, item => item.updateCount++); + }, + onUnmountComponent(id) { updateTree(id, item => item.isMounted = false); rootIDs = rootIDs.filter(rootID => rootID !== id); @@ -136,6 +141,11 @@ var ReactComponentTreeDevtool = { return item ? item.text : null; }, + getUpdateCount(id) { + var item = tree[id]; + return item ? item.updateCount : 0; + }, + getRootIDs() { return rootIDs; }, diff --git a/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js b/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js index 2ff1a58abb..106307d0d2 100644 --- a/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js +++ b/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js @@ -1697,6 +1697,31 @@ describe('ReactComponentTreeDevtool', () => { }); }); + it('reports update counts', () => { + var node = document.createElement('div'); + + ReactDOM.render(
, node); + var divID = ReactComponentTreeDevtool.getRootIDs()[0]; + expect(ReactComponentTreeDevtool.getUpdateCount(divID)).toEqual(0); + + ReactDOM.render(, node); + var spanID = ReactComponentTreeDevtool.getRootIDs()[0]; + expect(ReactComponentTreeDevtool.getUpdateCount(divID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(spanID)).toEqual(0); + + ReactDOM.render(, node); + expect(ReactComponentTreeDevtool.getUpdateCount(divID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(spanID)).toEqual(1); + + ReactDOM.render(, node); + expect(ReactComponentTreeDevtool.getUpdateCount(divID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(spanID)).toEqual(2); + + ReactDOM.unmountComponentAtNode(node); + expect(ReactComponentTreeDevtool.getUpdateCount(divID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(spanID)).toEqual(2); + }); + it('does not report top-level wrapper as a root', () => { var node = document.createElement('div'); diff --git a/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.native.js b/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.native.js index 4da93ab911..3113d6fcad 100644 --- a/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.native.js +++ b/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.native.js @@ -1685,6 +1685,29 @@ describe('ReactComponentTreeDevtool', () => { }); }); + it('reports update counts', () => { + ReactNative.render(, 1); + var viewID = ReactComponentTreeDevtool.getRootIDs()[0]; + expect(ReactComponentTreeDevtool.getUpdateCount(viewID)).toEqual(0); + + ReactNative.render(, 1); + var imageID = ReactComponentTreeDevtool.getRootIDs()[0]; + expect(ReactComponentTreeDevtool.getUpdateCount(viewID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(imageID)).toEqual(0); + + ReactNative.render(, 1); + expect(ReactComponentTreeDevtool.getUpdateCount(viewID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(imageID)).toEqual(1); + + ReactNative.render(, 1); + expect(ReactComponentTreeDevtool.getUpdateCount(viewID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(imageID)).toEqual(2); + + ReactNative.unmountComponentAtNode(1); + expect(ReactComponentTreeDevtool.getUpdateCount(viewID)).toEqual(0); + expect(ReactComponentTreeDevtool.getUpdateCount(imageID)).toEqual(2); + }); + it('does not report top-level wrapper as a root', () => { ReactNative.render(, 1); expect(getRootDisplayNames()).toEqual(['View']);