From 1ebffa59fe1c465bf10441334c2e60e7a76b32c2 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 22 Apr 2016 02:42:29 +0100 Subject: [PATCH] ReactComponentTreeDevtool should ignore TopLevelWrapper --- src/isomorphic/ReactDebugTool.js | 3 + .../devtools/ReactComponentTreeDevtool.js | 78 +++++++++++-------- .../ReactComponentTreeDevtool-test.js | 24 +++++- src/renderers/dom/client/ReactMount.js | 6 ++ 4 files changed, 73 insertions(+), 38 deletions(-) diff --git a/src/isomorphic/ReactDebugTool.js b/src/isomorphic/ReactDebugTool.js index 6dfd605b0b..8c45afedc2 100644 --- a/src/isomorphic/ReactDebugTool.js +++ b/src/isomorphic/ReactDebugTool.js @@ -58,6 +58,9 @@ var ReactDebugTool = { onSetState() { emitEvent('onSetState'); }, + onSetIsTopLevelWrapper(debugID, isTopLevelWrapper) { + emitEvent('onSetIsTopLevelWrapper', debugID, isTopLevelWrapper); + }, onSetIsComposite(debugID, isComposite) { emitEvent('onSetIsComposite', debugID, isComposite); }, diff --git a/src/isomorphic/devtools/ReactComponentTreeDevtool.js b/src/isomorphic/devtools/ReactComponentTreeDevtool.js index 0f65e1cfc2..fc30ffbbdb 100644 --- a/src/isomorphic/devtools/ReactComponentTreeDevtool.js +++ b/src/isomorphic/devtools/ReactComponentTreeDevtool.js @@ -13,11 +13,15 @@ var invariant = require('invariant'); +var isTopLevelWrapperByID = {}; var unmountedContainerIDs = []; var allChildIDsByContainerID = {}; var tree = {}; function updateTree(id, update) { + if (isTopLevelWrapperByID[id]) { + return; + } if (!tree[id]) { tree[id] = {}; } @@ -44,6 +48,13 @@ function purgeTree(id) { } var ReactComponentTreeDevtool = { + onSetIsTopLevelWrapper(id, isTopLevelWrapper) { + if (isTopLevelWrapper) { + delete tree[id]; + isTopLevelWrapperByID[id] = true; + } + }, + onSetIsComposite(id, isComposite) { updateTree(id, item => item.isComposite = isComposite); }, @@ -53,45 +64,44 @@ var ReactComponentTreeDevtool = { }, onSetChildren(id, nextChildIDs) { - var prevChildIDs; updateTree(id, item => { - prevChildIDs = item.childIDs || []; + var prevChildIDs = item.childIDs || []; item.childIDs = nextChildIDs; - }); - prevChildIDs.forEach(prevChildID => { - if (tree[prevChildID] && nextChildIDs.indexOf(prevChildID) === -1) { - tree[prevChildID].parentID = null; - } - }); + prevChildIDs.forEach(prevChildID => { + var prevChild = tree[prevChildID]; + if (prevChild && nextChildIDs.indexOf(prevChildID) === -1) { + prevChild.parentID = null; + } + }); - nextChildIDs.forEach(nextChildID => { - var item = tree[nextChildID]; + nextChildIDs.forEach(nextChildID => { + var nextChild = tree[nextChildID]; + invariant( + nextChild, + 'Expected devtool events to fire for the child ' + + 'before its parent includes it in onSetChildren().' + ); + invariant( + nextChild.isComposite != null, + 'Expected onSetIsComposite() to fire for the child ' + + 'before its parent includes it in onSetChildren().' + ); + invariant( + nextChild.displayName != null, + 'Expected onSetDisplayName() to fire for the child ' + + 'before its parent includes it in onSetChildren().' + ); + invariant( + nextChild.childIDs != null || nextChild.text != null, + 'Expected either onSetChildren() or onSetText() to fire for the child ' + + 'before its parent includes it in onSetChildren().' + ); - invariant( - item, - 'Expected devtool events to fire for the child ' + - 'before its parent includes it in onSetChildren().' - ); - invariant( - item.isComposite != null, - 'Expected onSetIsComposite() to fire for the child ' + - 'before its parent includes it in onSetChildren().' - ); - invariant( - item.displayName != null, - 'Expected onSetDisplayName() to fire for the child ' + - 'before its parent includes it in onSetChildren().' - ); - invariant( - item.childIDs != null || item.text != null, - 'Expected either onSetChildren() or onSetText() to fire for the child ' + - 'before its parent includes it in onSetChildren().' - ); - - if (tree[nextChildID] && prevChildIDs.indexOf(nextChildID) === -1) { - tree[nextChildID].parentID = id; - } + if (prevChildIDs.indexOf(nextChildID) === -1) { + nextChild.parentID = id; + } + }); }); }, diff --git a/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js b/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js index ced1b0f411..f8f8a8c4da 100644 --- a/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js +++ b/src/isomorphic/devtools/__tests__/ReactComponentTreeDevtool-test.js @@ -36,7 +36,7 @@ describe('ReactComponentTreeDevtool', () => { ReactDebugTool.removeDevtool(ReactComponentTreeDevtool); }); - function denormalizeTree( + function explodeTree( tree, rootID, includeOwner = false, @@ -54,7 +54,7 @@ describe('ReactComponentTreeDevtool', () => { if (item.childIDs) { result.children = item.childIDs.map(childID => - denormalizeTree(tree, childID, includeOwner, rootID) + explodeTree(tree, childID, includeOwner, rootID) ); } if (item.text != null) { @@ -89,7 +89,7 @@ describe('ReactComponentTreeDevtool', () => { pairs.forEach(([element, expectedTree]) => { currentElement = element; ReactDOM.render(, node); - expect(denormalizeTree( + expect(explodeTree( ReactComponentTreeDevtool.getTree(), rootInstance._renderedComponent._debugID, includeOwner @@ -103,7 +103,7 @@ describe('ReactComponentTreeDevtool', () => { pairs.forEach(([element, expectedTree]) => { currentElement = element; ReactDOMServer.renderToString(); - expect(denormalizeTree( + expect(explodeTree( ReactComponentTreeDevtool.getTree(), rootInstance._renderedComponent._debugID, includeOwner @@ -1831,4 +1831,20 @@ describe('ReactComponentTreeDevtool', () => { }; assertTreeMatches([element, tree], true); }); + + it('ignores top-level wrapper', () => { + var node = document.createElement('div'); + ReactDOM.render(
, node); + expect( + getRegisteredDisplayNames(ReactComponentTreeDevtool.getTree()) + ).toEqual(['div']); + ReactDOM.render(
, node); + expect( + getRegisteredDisplayNames(ReactComponentTreeDevtool.getTree()) + ).toEqual(['div']); + ReactDOM.unmountComponentAtNode(node); + expect( + getRegisteredDisplayNames(ReactComponentTreeDevtool.getTree()) + ).toEqual([]); + }); }); diff --git a/src/renderers/dom/client/ReactMount.js b/src/renderers/dom/client/ReactMount.js index bb6705ba15..87c9e1489a 100644 --- a/src/renderers/dom/client/ReactMount.js +++ b/src/renderers/dom/client/ReactMount.js @@ -332,6 +332,12 @@ var ReactMount = { ReactBrowserEventEmitter.ensureScrollValueMonitoring(); var componentInstance = instantiateReactComponent(nextElement); + if (__DEV__) { + ReactInstrumentation.debugTool.onSetIsTopLevelWrapper( + componentInstance._debugID, + true + ); + } // The initial render is synchronous but any updates that happen during // rendering, in componentWillMount or componentDidMount, will be batched