@samitouri / QOS-React-2 / commits / 5c5d2ec182

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;