diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js
index 468c200511..cfbe109833 100644
--- a/src/core/ReactCompositeComponent.js
+++ b/src/core/ReactCompositeComponent.js
@@ -451,17 +451,19 @@ var ReactCompositeComponentMixin = {
}
}
- if (this.componentDidMount) {
- transaction.getReactOnDOMReady().enqueue(this, this.componentDidMount);
- }
-
this._renderedComponent = this._renderValidatedComponent();
// Done with mounting, `setState` will now trigger UI changes.
this._compositeLifeCycleState = null;
this._lifeCycleState = ReactComponent.LifeCycle.MOUNTED;
- return this._renderedComponent.mountComponent(rootID, transaction);
+ var html = this._renderedComponent.mountComponent(rootID, transaction);
+
+ if (this.componentDidMount) {
+ transaction.getReactOnDOMReady().enqueue(this, this.componentDidMount);
+ }
+
+ return html;
},
/**
diff --git a/src/core/__tests__/ReactComponentLifeCycle-test.js b/src/core/__tests__/ReactComponentLifeCycle-test.js
index 4c1f92e465..9d809aaa5d 100644
--- a/src/core/__tests__/ReactComponentLifeCycle-test.js
+++ b/src/core/__tests__/ReactComponentLifeCycle-test.js
@@ -429,5 +429,71 @@ describe('ReactComponentLifeCycle', function() {
expect(instance.state.stateField).toBe('goodbye');
});
+ it('should call nested lifecycle methods in the right order', function() {
+ var log;
+ var logger = function(msg) {
+ return function() {
+ // return true for shouldComponentUpdate
+ log.push(msg);
+ return true;
+ };
+ };
+ var Outer = React.createClass({
+ render: function() {
+ return
;
+ },
+ componentWillMount: logger('outer componentWillMount'),
+ componentDidMount: logger('outer componentDidMount'),
+ componentWillReceiveProps: logger('outer componentWillReceiveProps'),
+ shouldComponentUpdate: logger('outer shouldComponentUpdate'),
+ componentWillUpdate: logger('outer componentWillUpdate'),
+ componentDidUpdate: logger('outer componentDidUpdate'),
+ componentWillUnmount: logger('outer componentWillUnmount')
+ });
+ var Inner = React.createClass({
+ render: function() {
+ return {this.props.x};
+ },
+ componentWillMount: logger('inner componentWillMount'),
+ componentDidMount: logger('inner componentDidMount'),
+ componentWillReceiveProps: logger('inner componentWillReceiveProps'),
+ shouldComponentUpdate: logger('inner shouldComponentUpdate'),
+ componentWillUpdate: logger('inner componentWillUpdate'),
+ componentDidUpdate: logger('inner componentDidUpdate'),
+ componentWillUnmount: logger('inner componentWillUnmount')
+ });
+ var instance;
+ var node;
+
+ log = [];
+ instance = ReactTestUtils.renderIntoDocument();
+ expect(log).toEqual([
+ 'outer componentWillMount',
+ 'inner componentWillMount',
+ 'inner componentDidMount',
+ 'outer componentDidMount'
+ ]);
+
+ log = [];
+ instance.setProps({x: 42});
+ expect(log).toEqual([
+ 'outer componentWillReceiveProps',
+ 'outer shouldComponentUpdate',
+ 'outer componentWillUpdate',
+ 'inner componentWillReceiveProps',
+ 'inner shouldComponentUpdate',
+ 'inner componentWillUpdate',
+ 'inner componentDidUpdate',
+ 'outer componentDidUpdate'
+ ]);
+
+ log = [];
+ instance.unmountComponent();
+ expect(log).toEqual([
+ 'outer componentWillUnmount',
+ 'inner componentWillUnmount'
+ ]);
+ });
+
});