@samitouri / QOS-React / commits / c9eb572a6f

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 });