Fix null node issue in ReactCSSTransitionGroup (#6958)
Keyan Zhang committed
Jun 3, 2016 at 13:42 UTC
c9eb572a6f6f97c919b2a736803cba61b01559e3
2 files changed
+53
-10
src/addons/transitions/ReactCSSTransitionGroupChild.js
+15
-10
@@ -89,7 +89,7 @@ var ReactCSSTransitionGroupChild = React.createClass({
89
CSSCore.addClass(node, className);
90
91
// Need to do this to actually trigger a transition.
92
- this.queueClass(activeClassName);
92
+ this.queueClassAndNode(activeClassName, node);
93
94
// If the user specified a timeout delay.
95
if (userSpecifiedDelay) {
@@ -102,26 +102,29 @@ var ReactCSSTransitionGroupChild = React.createClass({
102
}
103
},
104
105
- queueClass: function(className) {
106
- this.classNameQueue.push(className);
105
+ queueClassAndNode: function(className, node) {
106
+ this.classNameAndNodeQueue.push({
107
+ className: className,
108
+ node: node,
109
+ });
110
111
if (!this.timeout) {
109
- this.timeout = setTimeout(this.flushClassNameQueue, TICK);
112
+ this.timeout = setTimeout(this.flushClassNameAndNodeQueue, TICK);
113
}
114
},
115
113
- flushClassNameQueue: function() {
116
+ flushClassNameAndNodeQueue: function() {
117
if (this.isMounted()) {
115
- this.classNameQueue.forEach(
116
- CSSCore.addClass.bind(CSSCore, ReactDOM.findDOMNode(this))
117
- );
118
+ this.classNameAndNodeQueue.forEach(function(obj) {
119
+ CSSCore.addClass(obj.node, obj.className);
120
+ });
121
}
119
- this.classNameQueue.length = 0;
122
+ this.classNameAndNodeQueue.length = 0;
123
this.timeout = null;
124
},
125
126
componentWillMount: function() {
124
- this.classNameQueue = [];
127
+ this.classNameAndNodeQueue = [];
128
this.transitionTimeouts = [];
129
},
130
@@ -132,6 +135,8 @@ var ReactCSSTransitionGroupChild = React.createClass({
135
this.transitionTimeouts.forEach(function(timeout) {
136
clearTimeout(timeout);
137
});
138
+
139
+ this.classNameAndNodeQueue.length = 0;
140
},
141
142
componentWillAppear: function(done) {
src/addons/transitions/__tests__/ReactCSSTransitionGroup-test.js
+38
@@ -291,4 +291,42 @@ describe('ReactCSSTransitionGroup', function() {
291
// Testing that no exception is thrown here, as the timeout has been cleared.
292
jest.runAllTimers();
293
});
294
+
295
+ it('should handle unmounted elements properly', function() {
296
+ var Child = React.createClass({
297
+ render() {
298
+ if (!this.props.show) {
299
+ return null;
300
+ }
301
+ return <div />;
302
+ },
303
+ });
304
+
305
+ var Component = React.createClass({
306
+ getInitialState() {
307
+ return { showChild: true };
308
+ },
309
+
310
+ componentDidMount() {
311
+ this.setState({ showChild: false });
312
+ },
313
+
314
+ render() {
315
+ return (
316
+ <ReactCSSTransitionGroup
317
+ transitionName="yolo"
318
+ transitionAppear={true}
319
+ transitionAppearTimeout={0}
320
+ >
321
+ <Child show={this.state.showChild} />
322
+ </ReactCSSTransitionGroup>
323
+ );
324
+ },
325
+ });
326
+
327
+ ReactDOM.render(<Component/>, container);
328
+
329
+ // Testing that no exception is thrown here, as the timeout has been cleared.
330
+ jest.runAllTimers();
331
+ });
332
});