Skip to content

Commit

Permalink
Walk down internal tree to find DOM node
Browse files Browse the repository at this point in the history
This reduces our reliance on hierarchical IDs. If facebook#4983 merges, this can look at `._nativeNode` when present.
  • Loading branch information
sophiebits committed Sep 28, 2015
1 parent b82f3ab commit 769d0ee
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 12 deletions.
48 changes: 36 additions & 12 deletions src/renderers/dom/client/findDOMNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ var ReactMount = require('ReactMount');
var invariant = require('invariant');
var warning = require('warning');

function getNativeComponentFromComposite(inst) {
var renderedElement;

do {
renderedElement = inst._renderedElement;
if (typeof renderedElement === 'object' && renderedElement != null) {
inst = inst._renderedComponent;
} else {
// Empty or text component
return null;
}
} while (typeof renderedElement.type === 'function');

return inst;
}

/**
* Returns the DOM node rendered by this element.
*
Expand Down Expand Up @@ -47,19 +63,27 @@ function findDOMNode(componentOrElement) {
if (componentOrElement.nodeType === 1) {
return componentOrElement;
}
if (ReactInstanceMap.has(componentOrElement)) {
return ReactMount.getNodeFromInstance(componentOrElement);

var inst = ReactInstanceMap.get(componentOrElement);
if (inst) {
inst = getNativeComponentFromComposite(inst);
// TODO: Once we store the DOM node on the component instance, this can use
// that directly instead of searching the DOM.
return inst ? ReactMount.getNode(inst._rootNodeID) : null;
}

if (typeof componentOrElement.render === 'function') {
invariant(
false,
'findDOMNode was called on an unmounted component.'
);
} else {
invariant(
false,
'Element appears to be neither ReactComponent nor DOMNode (keys: %s)',
Object.keys(componentOrElement)
);
}
invariant(
componentOrElement.render == null ||
typeof componentOrElement.render !== 'function',
'findDOMNode was called on an unmounted component.'
);
invariant(
false,
'Element appears to be neither ReactComponent nor DOMNode (keys: %s)',
Object.keys(componentOrElement)
);
}

module.exports = findDOMNode;
4 changes: 4 additions & 0 deletions src/renderers/shared/reconciler/ReactCompositeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ var ReactCompositeComponentMixin = {
this._pendingReplaceState = false;
this._pendingForceUpdate = false;

this._renderedElement = null;
this._renderedComponent = null;

this._context = null;
Expand Down Expand Up @@ -280,6 +281,7 @@ var ReactCompositeComponentMixin = {
renderedElement = this._renderValidatedComponent();
}

this._renderedElement = renderedElement;
this._renderedComponent = this._instantiateReactComponent(
renderedElement
);
Expand Down Expand Up @@ -311,6 +313,7 @@ var ReactCompositeComponentMixin = {
}

ReactReconciler.unmountComponent(this._renderedComponent);
this._renderedElement = null;
this._renderedComponent = null;
this._instance = null;

Expand Down Expand Up @@ -732,6 +735,7 @@ var ReactCompositeComponentMixin = {
var prevComponentID = prevComponentInstance._rootNodeID;
ReactReconciler.unmountComponent(prevComponentInstance);

this._renderedElement = nextRenderedElement;
this._renderedComponent = this._instantiateReactComponent(
nextRenderedElement
);
Expand Down

0 comments on commit 769d0ee

Please sign in to comment.