ReactComponentTreeDevtool should ignore TopLevelWrapper

This commit is contained in:
Dan Abramov
2016-04-22 02:42:29 +01:00
parent e20d366ea8
commit 1ebffa59fe
4 changed files with 73 additions and 38 deletions
+3
View File
@@ -58,6 +58,9 @@ var ReactDebugTool = {
onSetState() {
emitEvent('onSetState');
},
onSetIsTopLevelWrapper(debugID, isTopLevelWrapper) {
emitEvent('onSetIsTopLevelWrapper', debugID, isTopLevelWrapper);
},
onSetIsComposite(debugID, isComposite) {
emitEvent('onSetIsComposite', debugID, isComposite);
},
@@ -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;
}
});
});
},
@@ -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(<Wrapper />, 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(<Wrapper />);
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(<div className="a" />, node);
expect(
getRegisteredDisplayNames(ReactComponentTreeDevtool.getTree())
).toEqual(['div']);
ReactDOM.render(<div className="b" />, node);
expect(
getRegisteredDisplayNames(ReactComponentTreeDevtool.getTree())
).toEqual(['div']);
ReactDOM.unmountComponentAtNode(node);
expect(
getRegisteredDisplayNames(ReactComponentTreeDevtool.getTree())
).toEqual([]);
});
});
+6
View File
@@ -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