diff --git a/src/addons/transitions/ReactCSSTransitionGroupChild.js b/src/addons/transitions/ReactCSSTransitionGroupChild.js
index 304232689c..c5332044f5 100644
--- a/src/addons/transitions/ReactCSSTransitionGroupChild.js
+++ b/src/addons/transitions/ReactCSSTransitionGroupChild.js
@@ -100,6 +100,7 @@ var ReactCSSTransitionGroupChild = React.createClass({
if (userSpecifiedDelay) {
// Clean-up the animation after the specified delay
timeout = setTimeout(endListener, userSpecifiedDelay);
+ this.transitionTimeouts.push(timeout);
} else {
// DEPRECATED: this listener will be removed in a future version of react
ReactTransitionEvents.addEndEventListener(node, endListener);
@@ -126,12 +127,16 @@ var ReactCSSTransitionGroupChild = React.createClass({
componentWillMount: function() {
this.classNameQueue = [];
+ this.transitionTimeouts = [];
},
componentWillUnmount: function() {
if (this.timeout) {
clearTimeout(this.timeout);
}
+ this.transitionTimeouts.forEach(function(timeout) {
+ clearTimeout(timeout);
+ });
},
componentWillAppear: function(done) {
diff --git a/src/addons/transitions/__tests__/ReactCSSTransitionGroup-test.js b/src/addons/transitions/__tests__/ReactCSSTransitionGroup-test.js
index b56eb237a2..ce1d14a4b9 100644
--- a/src/addons/transitions/__tests__/ReactCSSTransitionGroup-test.js
+++ b/src/addons/transitions/__tests__/ReactCSSTransitionGroup-test.js
@@ -269,4 +269,26 @@ describe('ReactCSSTransitionGroup', function() {
var leavingNode = ReactDOM.findDOMNode(a).childNodes[0];
expect(CSSCore.hasClass(leavingNode, 'custom-leaving')).toBe(true);
});
+
+ it('should clear transition timeouts when unmounted', function() {
+ var Component = React.createClass({
+ render: function() {
+ return (
+
+ {this.props.children}
+
+ );
+ },
+ });
+
+ ReactDOM.render(, container);
+ ReactDOM.render(, container);
+
+ ReactDOM.unmountComponentAtNode(container);
+
+ // Testing that no exception is thrown here, as the timeout has been cleared.
+ jest.runAllTimers();
+ });
});