Walk down internal tree to find DOM node
This reduces our reliance on hierarchical IDs.
Ben Alpert committed
Sep 27, 2015 at 16:22 UTC
5c5d2ec182e4f517b7f3b865d0277ed0dc4f0abd
7 files changed
+80
-83
src/renderers/dom/client/ReactMount.js
-19
@@ -17,9 +17,7 @@ var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
17
var ReactCurrentOwner = require('ReactCurrentOwner');
18
var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
19
var ReactElement = require('ReactElement');
20
-var ReactEmptyComponentRegistry = require('ReactEmptyComponentRegistry');
20
var ReactInstanceHandles = require('ReactInstanceHandles');
22
-var ReactInstanceMap = require('ReactInstanceMap');
21
var ReactMarkupChecksum = require('ReactMarkupChecksum');
22
var ReactPerf = require('ReactPerf');
23
var ReactReconciler = require('ReactReconciler');
@@ -175,21 +173,6 @@ function getNode(id) {
173
}
174
}
175
178
-/**
179
- * Finds the node with the supplied public React instance.
180
- *
181
- * @param {*} instance A public React instance.
182
- * @return {?DOMElement} DOM node with the suppled `id`.
183
- * @internal
184
- */
185
-function getNodeFromInstance(instance) {
186
- var id = ReactInstanceMap.get(instance)._rootNodeID;
187
- if (ReactEmptyComponentRegistry.isNullComponentID(id)) {
188
- return null;
189
- }
190
- return getNode(id);
191
-}
192
-
176
/**
177
* A node is "valid" if it is contained by a currently mounted container.
178
*
@@ -1073,8 +1056,6 @@ var ReactMount = {
1056
1057
getNode: getNode,
1058
1076
- getNodeFromInstance: getNodeFromInstance,
1077
-
1059
isValid: isValid,
1060
1061
purgeID: purgeID,
src/renderers/dom/client/findDOMNode.js
+34
-13
@@ -13,12 +13,27 @@
13
'use strict';
14
15
var ReactCurrentOwner = require('ReactCurrentOwner');
16
+var ReactDOMComponent = require('ReactDOMComponent');
17
var ReactInstanceMap = require('ReactInstanceMap');
17
-var ReactMount = require('ReactMount');
18
+var ReactNodeTypes = require('ReactNodeTypes');
19
20
var invariant = require('invariant');
21
var warning = require('warning');
22
23
+function getNativeComponentFromComposite(inst) {
24
+ var type;
25
+
26
+ while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {
27
+ inst = inst._renderedComponent;
28
+ }
29
+
30
+ if (type === ReactNodeTypes.NATIVE) {
31
+ return inst._renderedComponent;
32
+ } else if (type === ReactNodeTypes.EMPTY) {
33
+ return null;
34
+ }
35
+}
36
+
37
/**
38
* Returns the DOM node rendered by this element.
39
*
@@ -47,19 +62,25 @@ function findDOMNode(componentOrElement) {
62
if (componentOrElement.nodeType === 1) {
63
return componentOrElement;
64
}
50
- if (ReactInstanceMap.has(componentOrElement)) {
51
- return ReactMount.getNodeFromInstance(componentOrElement);
65
+
66
+ var inst = ReactInstanceMap.get(componentOrElement);
67
+ if (inst) {
68
+ inst = getNativeComponentFromComposite(inst);
69
+ return inst ? ReactDOMComponent.getNodeFromInstance(inst) : null;
70
+ }
71
+
72
+ if (typeof componentOrElement.render === 'function') {
73
+ invariant(
74
+ false,
75
+ 'findDOMNode was called on an unmounted component.'
76
+ );
77
+ } else {
78
+ invariant(
79
+ false,
80
+ 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)',
81
+ Object.keys(componentOrElement)
82
+ );
83
}
53
- invariant(
54
- componentOrElement.render == null ||
55
- typeof componentOrElement.render !== 'function',
56
- 'findDOMNode was called on an unmounted component.'
57
- );
58
- invariant(
59
- false,
60
- 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)',
61
- Object.keys(componentOrElement)
62
- );
84
}
85
86
module.exports = findDOMNode;
src/renderers/dom/shared/ReactDOMComponent.js
+4
@@ -1173,4 +1173,8 @@ assign(
1173
ReactMultiChild.Mixin
1174
);
1175
1176
+assign(ReactDOMComponent, {
1177
+ getNodeFromInstance: getNode,
1178
+});
1179
+
1180
module.exports = ReactDOMComponent;
src/renderers/shared/reconciler/ReactCompositeComponent.js
+5
@@ -15,6 +15,7 @@ var ReactComponentEnvironment = require('ReactComponentEnvironment');
15
var ReactCurrentOwner = require('ReactCurrentOwner');
16
var ReactElement = require('ReactElement');
17
var ReactInstanceMap = require('ReactInstanceMap');
18
+var ReactNodeTypes = require('ReactNodeTypes');
19
var ReactPerf = require('ReactPerf');
20
var ReactPropTypeLocations = require('ReactPropTypeLocations');
21
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
@@ -105,6 +106,7 @@ var ReactCompositeComponentMixin = {
106
this._pendingReplaceState = false;
107
this._pendingForceUpdate = false;
108
109
+ this._renderedNodeType = null;
110
this._renderedComponent = null;
111
112
this._context = null;
@@ -290,6 +292,7 @@ var ReactCompositeComponentMixin = {
292
renderedElement = this._renderValidatedComponent();
293
}
294
295
+ this._renderedNodeType = ReactNodeTypes.getType(renderedElement);
296
this._renderedComponent = this._instantiateReactComponent(
297
renderedElement
298
);
@@ -327,6 +330,7 @@ var ReactCompositeComponentMixin = {
330
}
331
332
ReactReconciler.unmountComponent(this._renderedComponent);
333
+ this._renderedNodeType = null;
334
this._renderedComponent = null;
335
this._instance = null;
336
@@ -752,6 +756,7 @@ var ReactCompositeComponentMixin = {
756
757
ReactReconciler.unmountComponent(prevComponentInstance);
758
759
+ this._renderedNodeType = ReactNodeTypes.getType(nextRenderedElement);
760
this._renderedComponent = this._instantiateReactComponent(
761
nextRenderedElement
762
);
src/renderers/shared/reconciler/ReactEmptyComponent.js
-3
@@ -12,7 +12,6 @@
12
'use strict';
13
14
var ReactElement = require('ReactElement');
15
-var ReactEmptyComponentRegistry = require('ReactEmptyComponentRegistry');
15
var ReactReconciler = require('ReactReconciler');
16
17
var assign = require('Object.assign');
@@ -40,7 +39,6 @@ assign(ReactEmptyComponent.prototype, {
39
nativeContainerInfo,
40
context
41
) {
43
- ReactEmptyComponentRegistry.registerNullComponentID(rootID);
42
this._rootNodeID = rootID;
43
return ReactReconciler.mountComponent(
44
this._renderedComponent,
@@ -58,7 +56,6 @@ assign(ReactEmptyComponent.prototype, {
56
},
57
unmountComponent: function(rootID, transaction, context) {
58
ReactReconciler.unmountComponent(this._renderedComponent);
61
- ReactEmptyComponentRegistry.deregisterNullComponentID(this._rootNodeID);
59
this._rootNodeID = null;
60
this._renderedComponent = null;
61
},
src/renderers/shared/reconciler/ReactEmptyComponentRegistry.js
deleted
-48
@@ -1,48 +0,0 @@
1
-/**
2
- * Copyright 2014-2015, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- *
9
- * @providesModule ReactEmptyComponentRegistry
10
- */
11
-
12
-'use strict';
13
-
14
-// This registry keeps track of the React IDs of the components that rendered to
15
-// `null` (in reality a placeholder such as `noscript`)
16
-var nullComponentIDsRegistry = {};
17
-
18
-/**
19
- * @param {string} id Component's `_rootNodeID`.
20
- * @return {boolean} True if the component is rendered to null.
21
- */
22
-function isNullComponentID(id) {
23
- return !!nullComponentIDsRegistry[id];
24
-}
25
-
26
-/**
27
- * Mark the component as having rendered to null.
28
- * @param {string} id Component's `_rootNodeID`.
29
- */
30
-function registerNullComponentID(id) {
31
- nullComponentIDsRegistry[id] = true;
32
-}
33
-
34
-/**
35
- * Unmark the component as having rendered to null: it renders to something now.
36
- * @param {string} id Component's `_rootNodeID`.
37
- */
38
-function deregisterNullComponentID(id) {
39
- delete nullComponentIDsRegistry[id];
40
-}
41
-
42
-var ReactEmptyComponentRegistry = {
43
- isNullComponentID: isNullComponentID,
44
- registerNullComponentID: registerNullComponentID,
45
- deregisterNullComponentID: deregisterNullComponentID,
46
-};
47
-
48
-module.exports = ReactEmptyComponentRegistry;
src/shared/utils/ReactNodeTypes.js
new
+37
@@ -0,0 +1,37 @@
1
+/**
2
+ * Copyright 2013-2015, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactNodeTypes
10
+ */
11
+
12
+'use strict';
13
+
14
+var ReactElement = require('ReactElement');
15
+
16
+var invariant = require('invariant');
17
+
18
+var ReactNodeTypes = {
19
+ NATIVE: 0,
20
+ COMPOSITE: 1,
21
+ EMPTY: 2,
22
+
23
+ getType: function(node) {
24
+ if (node === null || node === false) {
25
+ return ReactNodeTypes.EMPTY;
26
+ } else if (ReactElement.isValidElement(node)) {
27
+ if (typeof node.type === 'function') {
28
+ return ReactNodeTypes.COMPOSITE;
29
+ } else {
30
+ return ReactNodeTypes.NATIVE;
31
+ }
32
+ }
33
+ invariant(false, 'Unexpected node: %s', node);
34
+ },
35
+};
36
+
37
+module.exports = ReactNodeTypes;