diff --git a/src/renderers/dom/client/findDOMNode.js b/src/renderers/dom/client/findDOMNode.js index 870284446a0c4..b928b7defe8e5 100644 --- a/src/renderers/dom/client/findDOMNode.js +++ b/src/renderers/dom/client/findDOMNode.js @@ -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. * @@ -47,19 +63,29 @@ function findDOMNode(componentOrElement) { if (componentOrElement.nodeType === 1) { return componentOrElement; } - if (ReactInstanceMap.has(componentOrElement)) { - return ReactMount.getNodeFromInstance(componentOrElement); + + var inst = ReactInstanceMap.get(componentOrElement); + if (inst) { + if (typeof inst._currentElement.type === 'function') { + 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; diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index b96ece5133cfe..2f52b553ca4ef 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -103,6 +103,7 @@ var ReactCompositeComponentMixin = { this._pendingReplaceState = false; this._pendingForceUpdate = false; + this._renderedElement = null; this._renderedComponent = null; this._context = null; @@ -280,6 +281,7 @@ var ReactCompositeComponentMixin = { renderedElement = this._renderValidatedComponent(); } + this._renderedElement = renderedElement; this._renderedComponent = this._instantiateReactComponent( renderedElement ); @@ -311,6 +313,7 @@ var ReactCompositeComponentMixin = { } ReactReconciler.unmountComponent(this._renderedComponent); + this._renderedElement = null; this._renderedComponent = null; this._instance = null; @@ -732,6 +735,7 @@ var ReactCompositeComponentMixin = { var prevComponentID = prevComponentInstance._rootNodeID; ReactReconciler.unmountComponent(prevComponentInstance); + this._renderedElement = nextRenderedElement; this._renderedComponent = this._instantiateReactComponent( nextRenderedElement );