Consolidate hook events (#7472)

* Remove onBeforeMountComponent hook event

It is unnecessary.
We now pass the element as part of onInstantiateComponent, and it can't change before mounting.

* Remove onComponentHasMounted hook event

It is unused after #7410.

* Replace on(Begin|End)ReconcilerTimer hook events

We already have onBeforeUpdateComponent.
Let's just have on(Before?)(Mount|Update|Unmount)Component and stick with them.

This removes double event dispatches in some hot spots.

* Remove onComponentHasUpdated hook

The tests still pass so presumably it was not necessary.

* Add missing __DEV__ to TestUtils code

* Replace on(InstantiateComponent|SetParent) with onBeforeMountComponent

This lets us further consolidate hooks.
The parent ID is now passed as an argument to onBeforeMountComponent() with the element.

* Remove onMountRootComponent hook event

It is unnecessary now that we pass the parent ID to onBeforeMountComponent.

* Use parentDebugID = 0 both for roots and production

This removes some awkward branching.
This commit is contained in:
Dan Abramov
2016-08-11 19:35:50 +01:00
committed by GitHub
parent f7e0db9a18
commit 0e976e136c
15 changed files with 86 additions and 192 deletions
+17 -20
View File
@@ -39,11 +39,11 @@ function remove(id) {
delete itemByKey[key];
}
function create(id, element) {
function create(id, element, parentID) {
var key = getKeyFromID(id);
itemByKey[key] = {
element,
parentID: null,
parentID,
text: null,
childIDs: [],
isMounted: false,
@@ -133,8 +133,8 @@ var ReactComponentTreeHook = {
}
invariant(
nextChild.parentID === id,
'Expected onSetParent() and onSetChildren() to be consistent (%s ' +
'has parents %s and %s).',
'Expected onBeforeMountComponent() parent and onSetChildren() to ' +
'be consistent (%s has parents %s and %s).',
nextChildID,
nextChild.parentID,
id
@@ -142,18 +142,12 @@ var ReactComponentTreeHook = {
}
},
onSetParent(id, parentID) {
var item = get(id);
item.parentID = parentID;
},
onBeforeMountComponent(id, element, parentID) {
create(id, element, parentID);
onInstantiateComponent(id, element) {
create(id, element);
},
onBeforeMountComponent(id, element) {
var item = get(id);
item.element = element;
if (parentID === 0) {
rootIDs[id] = true;
}
},
onBeforeUpdateComponent(id, element) {
@@ -171,10 +165,6 @@ var ReactComponentTreeHook = {
item.isMounted = true;
},
onMountRootComponent(id) {
rootIDs[id] = true;
},
onUpdateComponent(id) {
var item = get(id);
if (!item || !item.isMounted) {
@@ -187,7 +177,14 @@ var ReactComponentTreeHook = {
onUnmountComponent(id) {
var item = get(id);
item.isMounted = false;
if (item) {
// We need to check if it exists.
// `item` might not exist if it is inside an error boundary, and a sibling
// error boundary child threw while mounting. Then this instance never
// got a chance to mount, but it still gets an unmounting event during
// the error boundary cleanup.
item.isMounted = false;
}
unmountedIDs[id] = true;
delete rootIDs[id];
},
+2 -8
View File
@@ -114,7 +114,8 @@ function mountComponentIntoNode(
transaction,
null,
ReactDOMContainerInfo(wrapperInstance, container),
context
context,
0 /* parentDebugID */
);
if (markerName) {
@@ -355,13 +356,6 @@ var ReactMount = {
var wrapperID = componentInstance._instance.rootID;
instancesByReactRootID[wrapperID] = componentInstance;
if (__DEV__) {
// The instance here is TopLevelWrapper so we report mount for its child.
ReactInstrumentation.debugTool.onMountRootComponent(
componentInstance._renderedComponent._debugID
);
}
return componentInstance;
},
@@ -47,7 +47,8 @@ function renderToStringImpl(element, makeStaticMarkup) {
transaction,
null,
ReactDOMContainerInfo(),
emptyObject
emptyObject,
0 /* parentDebugID */
);
if (__DEV__) {
ReactInstrumentation.debugTool.onUnmountComponent(
+1 -17
View File
@@ -274,9 +274,7 @@ if (__DEV__) {
ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);
ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);
} else {
ReactInstrumentation.debugTool.onInstantiateComponent(contentDebugID, content);
ReactInstrumentation.debugTool.onSetParent(contentDebugID, debugID);
ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content);
ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content, debugID);
ReactInstrumentation.debugTool.onMountComponent(contentDebugID);
ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);
}
@@ -707,13 +705,6 @@ ReactDOMComponent.Mixin = {
break;
}
if (__DEV__) {
if (this._debugID) {
var callback = () => ReactInstrumentation.debugTool.onComponentHasMounted(this._debugID);
transaction.getReactMountReady().enqueue(callback, this);
}
}
return mountImage;
},
@@ -943,13 +934,6 @@ ReactDOMComponent.Mixin = {
transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
break;
}
if (__DEV__) {
if (this._debugID) {
var callback = () => ReactInstrumentation.debugTool.onComponentHasUpdated(this._debugID);
transaction.getReactMountReady().enqueue(callback, this);
}
}
},
/**
+2 -7
View File
@@ -56,7 +56,8 @@ function mountComponentIntoNode(
transaction,
null,
ReactNativeContainerInfo(containerTag),
emptyObject
emptyObject,
0 /* parentDebugID */
);
componentInstance._renderedComponent._topLevelWrapper = componentInstance;
ReactNativeMount._mountImageIntoNode(markup, containerTag);
@@ -147,12 +148,6 @@ var ReactNativeMount = {
instance,
containerTag
);
if (__DEV__) {
// The instance here is TopLevelWrapper so we report mount for its child.
ReactInstrumentation.debugTool.onMountRootComponent(
instance._renderedComponent._debugID
);
}
var component = instance.getPublicInstance();
if (callback) {
callback.call(component);
+11 -31
View File
@@ -109,7 +109,10 @@ function resetMeasurements() {
currentFlushMeasurements = [];
}
function checkDebugID(debugID) {
function checkDebugID(debugID, allowRoot = false) {
if (allowRoot && debugID === 0) {
return;
}
if (!debugID) {
warning(false, 'ReactDebugTool: debugID may not be empty.');
}
@@ -248,14 +251,6 @@ var ReactDebugTool = {
endLifeCycleTimer(debugID, timerType);
emitEvent('onEndLifeCycleTimer', debugID, timerType);
},
onBeginReconcilerTimer(debugID, timerType) {
checkDebugID(debugID);
emitEvent('onBeginReconcilerTimer', debugID, timerType);
},
onEndReconcilerTimer(debugID, timerType) {
checkDebugID(debugID);
emitEvent('onEndReconcilerTimer', debugID, timerType);
},
onError(debugID) {
if (currentTimerDebugID != null) {
endLifeCycleTimer(currentTimerDebugID, currentTimerType);
@@ -272,14 +267,6 @@ var ReactDebugTool = {
checkDebugID(debugID);
emitEvent('onHostOperation', debugID, type, payload);
},
onComponentHasMounted(debugID) {
checkDebugID(debugID);
emitEvent('onComponentHasMounted', debugID);
},
onComponentHasUpdated(debugID) {
checkDebugID(debugID);
emitEvent('onComponentHasUpdated', debugID);
},
onSetState() {
emitEvent('onSetState');
},
@@ -288,21 +275,10 @@ var ReactDebugTool = {
childDebugIDs.forEach(checkDebugID);
emitEvent('onSetChildren', debugID, childDebugIDs);
},
onSetParent(debugID, parentDebugID) {
onBeforeMountComponent(debugID, element, parentDebugID) {
checkDebugID(debugID);
emitEvent('onSetParent', debugID, parentDebugID);
},
onInstantiateComponent(debugID, element) {
checkDebugID(debugID);
emitEvent('onInstantiateComponent', debugID, element);
},
onMountRootComponent(debugID) {
checkDebugID(debugID);
emitEvent('onMountRootComponent', debugID);
},
onBeforeMountComponent(debugID, element) {
checkDebugID(debugID);
emitEvent('onBeforeMountComponent', debugID, element);
checkDebugID(parentDebugID, true);
emitEvent('onBeforeMountComponent', debugID, element, parentDebugID);
},
onMountComponent(debugID) {
checkDebugID(debugID);
@@ -316,6 +292,10 @@ var ReactDebugTool = {
checkDebugID(debugID);
emitEvent('onUpdateComponent', debugID);
},
onBeforeUnmountComponent(debugID) {
checkDebugID(debugID);
emitEvent('onBeforeUnmountComponent', debugID);
},
onUnmountComponent(debugID) {
checkDebugID(debugID);
emitEvent('onUnmountComponent', debugID);
@@ -50,7 +50,7 @@ var ReactChildrenMutationWarningHook = {
onMountComponent(debugID) {
handleElement(debugID, ReactComponentTreeHook.getElement(debugID));
},
onComponentHasUpdated(debugID) {
onUpdateComponent(debugID) {
handleElement(debugID, ReactComponentTreeHook.getElement(debugID));
},
};
@@ -75,7 +75,7 @@ var ReactChildReconciler = {
nestedChildNodes,
transaction,
context,
selfDebugID // __DEV__ only
selfDebugID // 0 in production and for roots
) {
if (nestedChildNodes == null) {
return null;
@@ -117,7 +117,9 @@ var ReactChildReconciler = {
transaction,
hostParent,
hostContainerInfo,
context) {
context,
selfDebugID // 0 in production and for roots
) {
// We currently don't have a way to track moves here but if we use iterators
// instead of for..in we can zip the iterators and check if an item has
// moved.
@@ -156,7 +158,8 @@ var ReactChildReconciler = {
transaction,
hostParent,
hostContainerInfo,
context
context,
selfDebugID
);
mountImages.push(nextChildMountImage);
}
@@ -370,13 +370,6 @@ var ReactCompositeComponentMixin = {
}
}
if (__DEV__) {
if (this._debugID) {
var callback = (component) => ReactInstrumentation.debugTool.onComponentHasMounted(this._debugID);
transaction.getReactMountReady().enqueue(callback, this);
}
}
return markup;
},
@@ -532,21 +525,18 @@ var ReactCompositeComponentMixin = {
nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */
);
this._renderedComponent = child;
if (__DEV__) {
if (child._debugID !== 0 && this._debugID !== 0) {
ReactInstrumentation.debugTool.onSetParent(
child._debugID,
this._debugID
);
}
}
var selfDebugID = 0;
if (__DEV__) {
selfDebugID = this._debugID;
}
var markup = ReactReconciler.mountComponent(
child,
transaction,
hostParent,
hostContainerInfo,
this._processChildContext(context)
this._processChildContext(context),
selfDebugID
);
if (__DEV__) {
@@ -1024,13 +1014,6 @@ var ReactCompositeComponentMixin = {
);
}
}
if (__DEV__) {
if (this._debugID) {
var callback = () => ReactInstrumentation.debugTool.onComponentHasUpdated(this._debugID);
transaction.getReactMountReady().enqueue(callback, this);
}
}
},
/**
@@ -1061,21 +1044,18 @@ var ReactCompositeComponentMixin = {
nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */
);
this._renderedComponent = child;
if (__DEV__) {
if (child._debugID !== 0 && this._debugID !== 0) {
ReactInstrumentation.debugTool.onSetParent(
child._debugID,
this._debugID
);
}
}
var selfDebugID = 0;
if (__DEV__) {
selfDebugID = this._debugID;
}
var nextMarkup = ReactReconciler.mountComponent(
child,
transaction,
this._hostParent,
this._hostContainerInfo,
this._processChildContext(context)
this._processChildContext(context),
selfDebugID
);
if (__DEV__) {
@@ -140,7 +140,6 @@ function processQueue(inst, updateQueue) {
);
}
var setParentForInstrumentation = emptyFunction;
var setChildrenForInstrumentation = emptyFunction;
if (__DEV__) {
var getDebugID = function(inst) {
@@ -153,14 +152,6 @@ if (__DEV__) {
}
return inst._debugID;
};
setParentForInstrumentation = function(child) {
if (child._debugID !== 0) {
ReactInstrumentation.debugTool.onSetParent(
child._debugID,
getDebugID(this)
);
}
};
setChildrenForInstrumentation = function(children) {
var debugID = getDebugID(this);
// TODO: React Native empty components are also multichild.
@@ -193,11 +184,12 @@ var ReactMultiChild = {
_reconcilerInstantiateChildren: function(nestedChildren, transaction, context) {
if (__DEV__) {
var selfDebugID = getDebugID(this);
if (this._currentElement) {
try {
ReactCurrentOwner.current = this._currentElement._owner;
return ReactChildReconciler.instantiateChildren(
nestedChildren, transaction, context, this._debugID
nestedChildren, transaction, context, selfDebugID
);
} finally {
ReactCurrentOwner.current = null;
@@ -218,11 +210,13 @@ var ReactMultiChild = {
context
) {
var nextChildren;
var selfDebugID = 0;
if (__DEV__) {
selfDebugID = getDebugID(this);
if (this._currentElement) {
try {
ReactCurrentOwner.current = this._currentElement._owner;
nextChildren = flattenChildren(nextNestedChildrenElements, this._debugID);
nextChildren = flattenChildren(nextNestedChildrenElements, selfDebugID);
} finally {
ReactCurrentOwner.current = null;
}
@@ -234,12 +228,13 @@ var ReactMultiChild = {
transaction,
this,
this._hostContainerInfo,
context
context,
selfDebugID
);
return nextChildren;
}
}
nextChildren = flattenChildren(nextNestedChildrenElements);
nextChildren = flattenChildren(nextNestedChildrenElements, selfDebugID);
ReactChildReconciler.updateChildren(
prevChildren,
nextChildren,
@@ -248,7 +243,8 @@ var ReactMultiChild = {
transaction,
this,
this._hostContainerInfo,
context
context,
selfDebugID
);
return nextChildren;
},
@@ -272,15 +268,17 @@ var ReactMultiChild = {
for (var name in children) {
if (children.hasOwnProperty(name)) {
var child = children[name];
var selfDebugID = 0;
if (__DEV__) {
setParentForInstrumentation.call(this, child);
selfDebugID = getDebugID(this);
}
var mountImage = ReactReconciler.mountComponent(
child,
transaction,
this,
this._hostContainerInfo,
context
context,
selfDebugID
);
child._mountIndex = index++;
mountImages.push(mountImage);
@@ -42,17 +42,15 @@ var ReactReconciler = {
transaction,
hostParent,
hostContainerInfo,
context
context,
parentDebugID // 0 in production and for roots
) {
if (__DEV__) {
if (internalInstance._debugID !== 0) {
ReactInstrumentation.debugTool.onBeforeMountComponent(
internalInstance._debugID,
internalInstance._currentElement
);
ReactInstrumentation.debugTool.onBeginReconcilerTimer(
internalInstance._debugID,
'mountComponent'
internalInstance._currentElement,
parentDebugID
);
}
}
@@ -60,7 +58,8 @@ var ReactReconciler = {
transaction,
hostParent,
hostContainerInfo,
context
context,
parentDebugID
);
if (internalInstance._currentElement &&
internalInstance._currentElement.ref != null) {
@@ -68,10 +67,6 @@ var ReactReconciler = {
}
if (__DEV__) {
if (internalInstance._debugID !== 0) {
ReactInstrumentation.debugTool.onEndReconcilerTimer(
internalInstance._debugID,
'mountComponent'
);
ReactInstrumentation.debugTool.onMountComponent(
internalInstance._debugID
);
@@ -97,9 +92,8 @@ var ReactReconciler = {
unmountComponent: function(internalInstance, safely) {
if (__DEV__) {
if (internalInstance._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginReconcilerTimer(
internalInstance._debugID,
'unmountComponent'
ReactInstrumentation.debugTool.onBeforeUnmountComponent(
internalInstance._debugID
);
}
}
@@ -107,10 +101,6 @@ var ReactReconciler = {
internalInstance.unmountComponent(safely);
if (__DEV__) {
if (internalInstance._debugID !== 0) {
ReactInstrumentation.debugTool.onEndReconcilerTimer(
internalInstance._debugID,
'unmountComponent'
);
ReactInstrumentation.debugTool.onUnmountComponent(
internalInstance._debugID
);
@@ -154,10 +144,6 @@ var ReactReconciler = {
internalInstance._debugID,
nextElement
);
ReactInstrumentation.debugTool.onBeginReconcilerTimer(
internalInstance._debugID,
'receiveComponent'
);
}
}
@@ -180,10 +166,6 @@ var ReactReconciler = {
if (__DEV__) {
if (internalInstance._debugID !== 0) {
ReactInstrumentation.debugTool.onEndReconcilerTimer(
internalInstance._debugID,
'receiveComponent'
);
ReactInstrumentation.debugTool.onUpdateComponent(
internalInstance._debugID
);
@@ -218,10 +200,6 @@ var ReactReconciler = {
}
if (__DEV__) {
if (internalInstance._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginReconcilerTimer(
internalInstance._debugID,
'performUpdateIfNecessary'
);
ReactInstrumentation.debugTool.onBeforeUpdateComponent(
internalInstance._debugID,
internalInstance._currentElement
@@ -231,10 +209,6 @@ var ReactReconciler = {
internalInstance.performUpdateIfNecessary(transaction);
if (__DEV__) {
if (internalInstance._debugID !== 0) {
ReactInstrumentation.debugTool.onEndReconcilerTimer(
internalInstance._debugID,
'performUpdateIfNecessary'
);
ReactInstrumentation.debugTool.onUpdateComponent(
internalInstance._debugID
);
@@ -23,14 +23,16 @@ Object.assign(ReactSimpleEmptyComponent.prototype, {
transaction,
hostParent,
hostContainerInfo,
context
context,
parentDebugID // 0 in production and for roots
) {
return ReactReconciler.mountComponent(
this._renderedComponent,
transaction,
hostParent,
hostContainerInfo,
context
context,
parentDebugID
);
},
receiveComponent: function() {
@@ -14,7 +14,6 @@
var ReactCompositeComponent = require('ReactCompositeComponent');
var ReactEmptyComponent = require('ReactEmptyComponent');
var ReactHostComponent = require('ReactHostComponent');
var ReactInstrumentation = require('ReactInstrumentation');
var invariant = require('invariant');
var warning = require('warning');
@@ -126,13 +125,7 @@ function instantiateReactComponent(node, shouldHaveDebugID) {
instance._mountImage = null;
if (__DEV__) {
if (shouldHaveDebugID) {
var debugID = nextDebugID++;
instance._debugID = debugID;
ReactInstrumentation.debugTool.onInstantiateComponent(debugID, node);
} else {
instance._debugID = 0;
}
instance._debugID = shouldHaveDebugID ? nextDebugID++ : 0;
}
// Internal instances should fully constructed at this point, so they should
-7
View File
@@ -12,7 +12,6 @@
'use strict';
var ReactElement = require('ReactElement');
var ReactInstrumentation = require('ReactInstrumentation');
var ReactReconciler = require('ReactReconciler');
var ReactUpdates = require('ReactUpdates');
@@ -160,12 +159,6 @@ var ReactTestMount = {
batchedMountComponentIntoNode,
instance
);
if (__DEV__) {
// The instance here is TopLevelWrapper so we report mount for its child.
ReactInstrumentation.debugTool.onMountRootComponent(
instance._renderedComponent._debugID
);
}
return new ReactTestInstance(instance);
},
+5 -5
View File
@@ -23,7 +23,6 @@ var ReactElement = require('ReactElement');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
var ReactCompositeComponent = require('ReactCompositeComponent');
var ReactInstanceMap = require('ReactInstanceMap');
var ReactInstrumentation = require('ReactInstrumentation');
var ReactReconciler = require('ReactReconciler');
var ReactUpdates = require('ReactUpdates');
var SyntheticEvent = require('SyntheticEvent');
@@ -383,8 +382,10 @@ var nextDebugID = 1;
var NoopInternalComponent = function(element) {
this._renderedOutput = element;
this._currentElement = element;
this._debugID = nextDebugID++;
ReactInstrumentation.debugTool.onInstantiateComponent(this._debugID, element);
if (__DEV__) {
this._debugID = nextDebugID++;
}
};
NoopInternalComponent.prototype = {
@@ -413,7 +414,6 @@ var ShallowComponentWrapper = function(element) {
// TODO: Consolidate with instantiateReactComponent
if (__DEV__) {
this._debugID = nextDebugID++;
ReactInstrumentation.debugTool.onInstantiateComponent(this._debugID, element);
}
this.construct(element);
@@ -493,7 +493,7 @@ ReactShallowRenderer.prototype._render = function(element, transaction, context)
);
} else {
var instance = new ShallowComponentWrapper(element);
ReactReconciler.mountComponent(instance, transaction, null, null, context);
ReactReconciler.mountComponent(instance, transaction, null, null, context, 0);
this._instance = instance;
}
};