diff --git a/src/browser/ReactTextComponent.js b/src/browser/ReactTextComponent.js index 24ea723729d91..7af125e51423c 100644 --- a/src/browser/ReactTextComponent.js +++ b/src/browser/ReactTextComponent.js @@ -23,6 +23,7 @@ var DOMPropertyOperations = require('DOMPropertyOperations'); var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin'); var ReactComponent = require('ReactComponent'); var ReactDescriptor = require('ReactDescriptor'); +var ReactNode = require('ReactNode'); var escapeTextForBrowser = require('escapeTextForBrowser'); var mixInto = require('mixInto'); @@ -47,6 +48,7 @@ var ReactTextComponent = function(descriptor) { }; mixInto(ReactTextComponent, ReactComponent.Mixin); +mixInto(ReactTextComponent, ReactNode.Mixin); mixInto(ReactTextComponent, ReactBrowserComponentMixin); mixInto(ReactTextComponent, { @@ -60,9 +62,10 @@ mixInto(ReactTextComponent, { * @return {string} Markup for this text node. * @internal */ - mountComponent: function(rootID, transaction, mountDepth) { + mountComponent: function(parentNode, rootID, transaction, mountDepth) { ReactComponent.Mixin.mountComponent.call( this, + parentNode, rootID, transaction, mountDepth diff --git a/src/browser/server/ReactServerRendering.js b/src/browser/server/ReactServerRendering.js index cf61cc4aaab5f..af130caaabe7c 100644 --- a/src/browser/server/ReactServerRendering.js +++ b/src/browser/server/ReactServerRendering.js @@ -50,7 +50,7 @@ function renderComponentToString(component) { return transaction.perform(function() { var componentInstance = instantiateReactComponent(component); - var markup = componentInstance.mountComponent(id, transaction, 0); + var markup = componentInstance.mountComponent(null, id, transaction, 0); return ReactMarkupChecksum.addChecksumToMarkup(markup); }, null); } finally { @@ -76,7 +76,7 @@ function renderComponentToStaticMarkup(component) { return transaction.perform(function() { var componentInstance = instantiateReactComponent(component); - return componentInstance.mountComponent(id, transaction, 0); + return componentInstance.mountComponent(null, id, transaction, 0); }, null); } finally { ReactServerRenderingTransaction.release(transaction); diff --git a/src/browser/ui/ReactDOMComponent.js b/src/browser/ui/ReactDOMComponent.js index 70c0ceb9e0a8a..c77bf06b4a820 100644 --- a/src/browser/ui/ReactDOMComponent.js +++ b/src/browser/ui/ReactDOMComponent.js @@ -27,6 +27,7 @@ var ReactComponent = require('ReactComponent'); var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); var ReactMount = require('ReactMount'); var ReactMultiChild = require('ReactMultiChild'); +var ReactNode = require('ReactNode'); var ReactPerf = require('ReactPerf'); var escapeTextForBrowser = require('escapeTextForBrowser'); @@ -83,7 +84,7 @@ function putListener(id, registrationName, listener, transaction) { /** * @constructor ReactDOMComponent - * @extends ReactComponent + * @extends ReactNodeComponent * @extends ReactMultiChild */ function ReactDOMComponent(tag, omitClose) { @@ -107,9 +108,10 @@ ReactDOMComponent.Mixin = { mountComponent: ReactPerf.measure( 'ReactDOMComponent', 'mountComponent', - function(rootID, transaction, mountDepth) { + function(parentNode, rootID, transaction, mountDepth) { ReactComponent.Mixin.mountComponent.call( this, + parentNode, rootID, transaction, mountDepth @@ -412,6 +414,7 @@ ReactDOMComponent.Mixin = { mixInto(ReactDOMComponent, ReactComponent.Mixin); mixInto(ReactDOMComponent, ReactDOMComponent.Mixin); +mixInto(ReactDOMComponent, ReactNode.Mixin); mixInto(ReactDOMComponent, ReactMultiChild.Mixin); mixInto(ReactDOMComponent, ReactBrowserComponentMixin); diff --git a/src/browser/ui/__tests__/ReactDOMComponent-test.js b/src/browser/ui/__tests__/ReactDOMComponent-test.js index b283a004e9a7d..faffcd9a5a275 100644 --- a/src/browser/ui/__tests__/ReactDOMComponent-test.js +++ b/src/browser/ui/__tests__/ReactDOMComponent-test.js @@ -333,7 +333,7 @@ describe('ReactDOMComponent', function() { _owner: null, _context: null }); - return stubComponent.mountComponent('test', transaction, 0); + return stubComponent.mountComponent(null, 'test', transaction, 0); }; }); diff --git a/src/browser/ui/dom/__tests__/Danger-test.js b/src/browser/ui/dom/__tests__/Danger-test.js index 698eeb6dc8fc0..6be499b65a9d0 100644 --- a/src/browser/ui/dom/__tests__/Danger-test.js +++ b/src/browser/ui/dom/__tests__/Danger-test.js @@ -40,7 +40,7 @@ describe('Danger', function() { it('should render markup', function() { var markup = instantiateReactComponent(
- ).mountComponent('.rX', transaction, 0); + ).mountComponent(null, '.rX', transaction, 0); var output = Danger.dangerouslyRenderMarkup([markup])[0]; expect(output.nodeName).toBe('DIV'); @@ -49,11 +49,7 @@ describe('Danger', function() { it('should render markup with props', function() { var markup = instantiateReactComponent(
- ).mountComponent( - '.rX', - transaction, - 0 - ); + ).mountComponent(null, '.rX', transaction, 0); var output = Danger.dangerouslyRenderMarkup([markup])[0]; expect(output.nodeName).toBe('DIV'); @@ -63,7 +59,7 @@ describe('Danger', function() { it('should render wrapped markup', function() { var markup = instantiateReactComponent( - ).mountComponent('.rX', transaction, 0); + ).mountComponent(null, '.rX', transaction, 0); var output = Danger.dangerouslyRenderMarkup([markup])[0]; expect(output.nodeName).toBe('TH'); diff --git a/src/core/ReactComponent.js b/src/core/ReactComponent.js index 355e65f667f60..8667e195de6c8 100644 --- a/src/core/ReactComponent.js +++ b/src/core/ReactComponent.js @@ -251,7 +251,7 @@ var ReactComponent = { * @return {?string} Rendered markup to be inserted into the DOM. * @internal */ - mountComponent: function(rootID, transaction, mountDepth) { + mountComponent: function(parentNode, rootID, transaction, mountDepth) { invariant( !this.isMounted(), 'mountComponent(%s, ...): Can only mount an unmounted component. ' + @@ -264,6 +264,7 @@ var ReactComponent = { var owner = this._descriptor._owner; ReactOwner.addComponentAsRefTo(this, ref, owner); } + this._parentNode = parentNode; this._rootNodeID = rootID; this._lifeCycleState = ComponentLifeCycle.MOUNTED; this._mountDepth = mountDepth; @@ -409,7 +410,7 @@ var ReactComponent = { container, transaction, shouldReuseMarkup) { - var markup = this.mountComponent(rootID, transaction, 0); + var markup = this.mountComponent(null, rootID, transaction, 0); mountImageIntoNode(markup, container, shouldReuseMarkup); }, @@ -439,6 +440,10 @@ var ReactComponent = { return null; } return owner.refs[ref]; + }, + + getClosestNode: function() { + return this._parentNode; } } }; diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index 42a1dcb45b575..0b900e26c08c9 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -731,9 +731,10 @@ var ReactCompositeComponentMixin = { mountComponent: ReactPerf.measure( 'ReactCompositeComponent', 'mountComponent', - function(rootID, transaction, mountDepth) { + function(parentNode, rootID, transaction, mountDepth) { ReactComponent.Mixin.mountComponent.call( this, + parentNode, rootID, transaction, mountDepth @@ -774,6 +775,7 @@ var ReactCompositeComponentMixin = { // Done with mounting, `setState` will now trigger UI changes. this._compositeLifeCycleState = null; var markup = this._renderedComponent.mountComponent( + this.getClosestNode(), rootID, transaction, mountDepth + 1 @@ -1162,6 +1164,7 @@ var ReactCompositeComponentMixin = { prevComponentInstance.unmountComponent(); this._renderedComponent = instantiateReactComponent(nextDescriptor); var nextMarkup = this._renderedComponent.mountComponent( + this.getClosestNode(), thisID, transaction, this._mountDepth + 1 diff --git a/src/core/ReactMultiChild.js b/src/core/ReactMultiChild.js index 608fe62d8461a..8622b81bc5777 100644 --- a/src/core/ReactMultiChild.js +++ b/src/core/ReactMultiChild.js @@ -200,6 +200,7 @@ var ReactMultiChild = { // Inlined for performance, see `ReactInstanceHandles.createReactID`. var rootID = this._rootNodeID + name; var mountImage = childInstance.mountComponent( + this.getClosestNode(), rootID, transaction, this._mountDepth + 1 @@ -397,6 +398,7 @@ var ReactMultiChild = { // Inlined for performance, see `ReactInstanceHandles.createReactID`. var rootID = this._rootNodeID + name; var mountImage = child.mountComponent( + this.getClosestNode(), rootID, transaction, this._mountDepth + 1 diff --git a/src/core/ReactNode.js b/src/core/ReactNode.js new file mode 100644 index 0000000000000..3198dfe7c60f5 --- /dev/null +++ b/src/core/ReactNode.js @@ -0,0 +1,33 @@ +/** + * Copyright 2013-2014 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule ReactNode + */ + +"use strict"; + +var ReactNode = { + + Mixin: { + + getClosestNode: function() { + return this; + } + + } + +}; + +module.exports = ReactNode;