diff --git a/src/browser/server/ReactServerRendering.js b/src/browser/server/ReactServerRendering.js
index d29989e0cb710..fb5c45c37bd6f 100644
--- a/src/browser/server/ReactServerRendering.js
+++ b/src/browser/server/ReactServerRendering.js
@@ -40,7 +40,7 @@ function renderToString(element, context) {
return transaction.perform(function() {
var componentInstance = instantiateReactComponent(element, null);
- var markup = componentInstance.mountComponent(id, transaction, 0, context);
+ var markup = componentInstance.mountComponent(id, transaction, context);
return ReactMarkupChecksum.addChecksumToMarkup(markup);
}, null);
} finally {
@@ -68,7 +68,7 @@ function renderToStaticMarkup(element, context) {
return transaction.perform(function() {
var componentInstance = instantiateReactComponent(element, null);
- return componentInstance.mountComponent(id, transaction, 0, context);
+ return componentInstance.mountComponent(id, transaction, context);
}, null);
} finally {
ReactServerRenderingTransaction.release(transaction);
diff --git a/src/browser/ui/ReactDOMComponent.js b/src/browser/ui/ReactDOMComponent.js
index 5216a530e2d2f..42a044d15d10a 100644
--- a/src/browser/ui/ReactDOMComponent.js
+++ b/src/browser/ui/ReactDOMComponent.js
@@ -168,15 +168,13 @@ ReactDOMComponent.Mixin = {
* @internal
* @param {string} rootID The root DOM ID for this node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
- * @param {number} mountDepth number of components in the owner hierarchy
* @return {string} The computed markup.
*/
- mountComponent: function(rootID, transaction, mountDepth, context) {
+ mountComponent: function(rootID, transaction, context) {
ReactComponent.Mixin.mountComponent.call(
this,
rootID,
transaction,
- mountDepth,
context
);
this._rootNodeID = rootID;
diff --git a/src/browser/ui/ReactDOMTextComponent.js b/src/browser/ui/ReactDOMTextComponent.js
index 54e5c7acf2e9e..e12ee2753a950 100644
--- a/src/browser/ui/ReactDOMTextComponent.js
+++ b/src/browser/ui/ReactDOMTextComponent.js
@@ -62,11 +62,10 @@ assign(ReactDOMTextComponent.prototype, {
*
* @param {string} rootID DOM ID of the root node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
- * @param {number} mountDepth number of components in the owner hierarchy
* @return {string} Markup for this text node.
* @internal
*/
- mountComponent: function(rootID, transaction, mountDepth, context) {
+ mountComponent: function(rootID, transaction, context) {
this._rootNodeID = rootID;
var escapedText = escapeTextForBrowser(this._stringText);
diff --git a/src/browser/ui/ReactMount.js b/src/browser/ui/ReactMount.js
index 90a874622d748..218a020667d5c 100644
--- a/src/browser/ui/ReactMount.js
+++ b/src/browser/ui/ReactMount.js
@@ -225,7 +225,8 @@ function mountComponentIntoNode(
container,
transaction,
shouldReuseMarkup) {
- var markup = this.mountComponent(rootID, transaction, 0, emptyObject);
+ var markup = this.mountComponent(rootID, transaction, emptyObject);
+ this._isTopLevel = true;
ReactMount._mountImageIntoNode(markup, container, shouldReuseMarkup);
}
diff --git a/src/browser/ui/__tests__/ReactDOMComponent-test.js b/src/browser/ui/__tests__/ReactDOMComponent-test.js
index 5427b832ba327..7bb8e24650216 100644
--- a/src/browser/ui/__tests__/ReactDOMComponent-test.js
+++ b/src/browser/ui/__tests__/ReactDOMComponent-test.js
@@ -328,7 +328,7 @@ describe('ReactDOMComponent', function() {
_owner: null,
_context: null
});
- return stubComponent.mountComponent('test', transaction, 0, {});
+ return stubComponent.mountComponent('test', transaction, {});
};
});
diff --git a/src/browser/ui/dom/__tests__/Danger-test.js b/src/browser/ui/dom/__tests__/Danger-test.js
index 1e2e6f02d338e..69f71c4655e80 100644
--- a/src/browser/ui/dom/__tests__/Danger-test.js
+++ b/src/browser/ui/dom/__tests__/Danger-test.js
@@ -32,7 +32,7 @@ describe('Danger', function() {
it('should render markup', function() {
var markup = instantiateReactComponent(
- ).mountComponent('.rX', transaction, 0, {});
+ ).mountComponent('.rX', transaction, {});
var output = Danger.dangerouslyRenderMarkup([markup])[0];
expect(output.nodeName).toBe('DIV');
@@ -44,7 +44,7 @@ describe('Danger', function() {
).mountComponent(
'.rX',
transaction,
- 0, {}
+ {}
);
var output = Danger.dangerouslyRenderMarkup([markup])[0];
@@ -55,7 +55,7 @@ describe('Danger', function() {
it('should render wrapped markup', function() {
var markup = instantiateReactComponent(
|
- ).mountComponent('.rX', transaction, 0, {});
+ ).mountComponent('.rX', transaction, {});
var output = Danger.dangerouslyRenderMarkup([markup])[0];
expect(output.nodeName).toBe('TH');
diff --git a/src/core/ReactComponent.js b/src/core/ReactComponent.js
index f9361bac20350..694d9578dd171 100644
--- a/src/core/ReactComponent.js
+++ b/src/core/ReactComponent.js
@@ -90,7 +90,6 @@ var ReactComponent = {
// to track updates.
this._currentElement = element;
this._mountIndex = 0;
- this._mountDepth = 0;
},
/**
@@ -103,17 +102,15 @@ var ReactComponent = {
*
* @param {string} rootID DOM ID of the root node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
- * @param {number} mountDepth number of components in the owner hierarchy.
* @return {?string} Rendered markup to be inserted into the DOM.
* @internal
*/
- mountComponent: function(rootID, transaction, mountDepth, context) {
+ mountComponent: function(rootID, transaction, context) {
var ref = this._currentElement.ref;
if (ref != null) {
var owner = this._currentElement._owner;
attachRef(ref, this, owner);
}
- this._mountDepth = mountDepth;
// Effectively: return '';
},
diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js
index bb43da310f1f5..192de12e4eb87 100644
--- a/src/core/ReactCompositeComponent.js
+++ b/src/core/ReactCompositeComponent.js
@@ -141,6 +141,7 @@ var ReactCompositeComponentMixin = assign({},
this._context = null;
this._mountOrder = 0;
+ this._isTopLevel = false;
// See ReactUpdates.
this._pendingCallbacks = null;
@@ -161,17 +162,15 @@ var ReactCompositeComponentMixin = assign({},
*
* @param {string} rootID DOM ID of the root node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
- * @param {number} mountDepth number of components in the owner hierarchy
* @return {?string} Rendered markup to be inserted into the DOM.
* @final
* @internal
*/
- mountComponent: function(rootID, transaction, mountDepth, context) {
+ mountComponent: function(rootID, transaction, context) {
ReactComponent.Mixin.mountComponent.call(
this,
rootID,
transaction,
- mountDepth,
context
);
@@ -233,7 +232,6 @@ var ReactCompositeComponentMixin = assign({},
var markup = this._renderedComponent.mountComponent(
rootID,
transaction,
- mountDepth + 1,
this._processChildContext(context)
);
if (inst.componentDidMount) {
@@ -313,7 +311,7 @@ var ReactCompositeComponentMixin = assign({},
*/
replaceProps: function(props, callback) {
invariant(
- this._mountDepth === 0,
+ this._isTopLevel,
'replaceProps(...): You called `setProps` or `replaceProps` on a ' +
'component with a parent. This is an anti-pattern since props will ' +
'get reactively updated when rendered. Instead, change the owner\'s ' +
@@ -781,7 +779,6 @@ var ReactCompositeComponentMixin = assign({},
var nextMarkup = this._renderedComponent.mountComponent(
thisID,
transaction,
- this._mountDepth + 1,
context
);
ReactComponentEnvironment.replaceNodeWithMarkupByID(
@@ -890,17 +887,15 @@ var ShallowMixin = assign({},
*
* @param {string} rootID DOM ID of the root node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
- * @param {number} mountDepth number of components in the owner hierarchy
* @return {ReactElement} Shallow rendering of the component.
* @final
* @internal
*/
- mountComponent: function(rootID, transaction, mountDepth, context) {
+ mountComponent: function(rootID, transaction, context) {
ReactComponent.Mixin.mountComponent.call(
this,
rootID,
transaction,
- mountDepth,
context
);
diff --git a/src/core/ReactMultiChild.js b/src/core/ReactMultiChild.js
index a6314fa87128c..15cf15b73fefe 100644
--- a/src/core/ReactMultiChild.js
+++ b/src/core/ReactMultiChild.js
@@ -195,7 +195,6 @@ var ReactMultiChild = {
var mountImage = childInstance.mountComponent(
rootID,
transaction,
- this._mountDepth + 1,
context
);
childInstance._mountIndex = index;
@@ -401,7 +400,6 @@ var ReactMultiChild = {
var mountImage = child.mountComponent(
rootID,
transaction,
- this._mountDepth + 1,
context
);
child._mountIndex = index;
diff --git a/src/core/__tests__/ReactComponent-test.js b/src/core/__tests__/ReactComponent-test.js
index 3b09fb2f52870..31b15549c84f5 100644
--- a/src/core/__tests__/ReactComponent-test.js
+++ b/src/core/__tests__/ReactComponent-test.js
@@ -16,7 +16,6 @@ var ReactInstanceMap;
var ReactTestUtils;
var reactComponentExpect;
-var getMountDepth;
describe('ReactComponent', function() {
beforeEach(function() {
@@ -24,10 +23,6 @@ describe('ReactComponent', function() {
ReactInstanceMap = require('ReactInstanceMap');
ReactTestUtils = require('ReactTestUtils');
reactComponentExpect = require('reactComponentExpect');
-
- getMountDepth = function(instance) {
- return ReactInstanceMap.get(instance)._mountDepth;
- };
});
it('should throw on invalid render targets', function() {
@@ -231,80 +226,4 @@ describe('ReactComponent', function() {
var instance = ReactTestUtils.renderIntoDocument(element);
expect(instance.isMounted()).toBeTruthy();
});
-
- it('should know its simple mount depth', function() {
- var Owner = React.createClass({
- render: function() {
- return ;
- }
- });
-
- var Child = React.createClass({
- render: function() {
- return ;
- }
- });
-
- var instance = ;
- instance = ReactTestUtils.renderIntoDocument(instance);
- expect(getMountDepth(instance)).toBe(0);
- expect(getMountDepth(instance.refs.child)).toBe(1);
- });
-
- it('should know its (complicated) mount depth', function() {
- var Box = React.createClass({
- render: function() {
- return {this.props.children}
;
- }
- });
-
- var Child = React.createClass({
- render: function() {
- return child;
- }
- });
-
- var Switcher = React.createClass({
- getInitialState: function() {
- return {tabKey: 'hello'};
- },
-
- render: function() {
- var child = this.props.children;
-
- return (
-
-
- {child}
-
-
- );
- }
- });
-
- var App = React.createClass({
- render: function() {
- return (
-
-
-
- );
- }
- });
-
- var root = ;
- root = ReactTestUtils.renderIntoDocument(root);
-
- expect(getMountDepth(root)).toBe(0);
- expect(getMountDepth(root.refs.switcher)).toBe(1);
- expect(getMountDepth(root.refs.switcher.refs.box)).toBe(2);
- expect(getMountDepth(root.refs.switcher.refs.switcherDiv)).toBe(5);
- expect(getMountDepth(root.refs.child)).toBe(7);
- expect(getMountDepth(root.refs.switcher.refs.box.refs.boxDiv)).toBe(3);
- expect(getMountDepth(root.refs.child.refs.span)).toBe(8);
- });
});
diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js
index a8e41988cb9f8..c31c88d462253 100644
--- a/src/core/__tests__/ReactCompositeComponent-test.js
+++ b/src/core/__tests__/ReactCompositeComponent-test.js
@@ -529,6 +529,34 @@ describe('ReactCompositeComponent', function() {
);
});
+ it('should only allow `setProps` on top-level components', function() {
+ var container = document.createElement('div');
+ document.documentElement.appendChild(container);
+
+ var innerInstance;
+
+ var Component = React.createClass({
+ render: function() {
+ return ;
+ },
+ componentDidMount: function() {
+ innerInstance = this.refs.inner;
+ }
+ });
+ React.render(, container);
+
+ expect(innerInstance).not.toBe(undefined);
+ expect(function() {
+ innerInstance.setProps({value: 1});
+ }).toThrow(
+ 'Invariant Violation: replaceProps(...): You called `setProps` or ' +
+ '`replaceProps` on a component with a parent. This is an anti-pattern ' +
+ 'since props will get reactively updated when rendered. Instead, ' +
+ 'change the owner\'s `render` method to pass the correct value as ' +
+ 'props to the component where it is created.'
+ );
+ });
+
it('should cleanup even if render() fatals', function() {
var BadComponent = React.createClass({
render: function() {
diff --git a/src/test/ReactTestUtils.js b/src/test/ReactTestUtils.js
index 9b148d188f531..8871a8c12ca29 100644
--- a/src/test/ReactTestUtils.js
+++ b/src/test/ReactTestUtils.js
@@ -340,7 +340,7 @@ ReactShallowRenderer.prototype._render = function(element, transaction, context)
var instance = new ShallowComponentWrapper(new element.type(element.props));
instance.construct(element);
- instance.mountComponent(rootID, transaction, 0, context);
+ instance.mountComponent(rootID, transaction, context);
this._instance = instance;
} else {