ReactCSSTransitionGroup leaves DOM nodes with both `leave` and `enter` classes #1707

Closed
victor-homyakov opened this Issue Jun 17, 2014 · 26 comments

Comments

Projects
None yet
@victor-homyakov
Contributor

victor-homyakov commented Jun 17, 2014

After sequence of fast changes (add/delete operations) nodes under ReactCSSTransitionGroup are left stuck with classes example-leave example-enter-active example-leave-active. Further state modifications do not change rendered DOM tree. Console has multiple warnings

transition(): tried to perform an animation without an animationend or transitionend event after timeout (5000ms). You should either disable this transition in JS or add a CSS animation/transition. 

Test page: http://jsbin.com/kasurusa/2

  1. Place cursor in input field
  2. Type l then type Backspace very fast
  3. Repeat step 2 few times

Easily reproduces in IE10, but could be also reproduced in Chrome 35.

@victor-homyakov

This comment has been minimized.

Show comment
Hide comment
@victor-homyakov

victor-homyakov Jun 17, 2014

Contributor

Code in ReactCSSTransitionGroupChild sometimes is executed in wrong sequence.

It assumes that independent asynchronous callbacks flushClassNameQueue and endListener are always executed in proper sequence:

  1. transition('leave')

    1.1 CSSCore.addClass(node, 'example-leave')

  2. flushClassNameQueue

    2.1 CSSCore.addClass(this.getDOMNode(), 'example-leave-active')

  3. endListener

    3.1 CSSCore.removeClass(node, 'example-leave'); CSSCore.removeClass(node, 'example-leave-active');

What sometimes happens:

  1. transition('leave')

    1.1 CSSCore.addClass(node, 'example-leave') - initiates CSS transition

  2. endListener - transition is finished

    2.1 CSSCore.removeClass(node, 'example-leave'); CSSCore.removeClass(node, 'example-leave-active');

  3. flushClassNameQueue - only then setTimeout timer fired

    3.1 CSSCore.addClass(this.getDOMNode(), 'example-leave-active')

Contributor

victor-homyakov commented Jun 17, 2014

Code in ReactCSSTransitionGroupChild sometimes is executed in wrong sequence.

It assumes that independent asynchronous callbacks flushClassNameQueue and endListener are always executed in proper sequence:

  1. transition('leave')

    1.1 CSSCore.addClass(node, 'example-leave')

  2. flushClassNameQueue

    2.1 CSSCore.addClass(this.getDOMNode(), 'example-leave-active')

  3. endListener

    3.1 CSSCore.removeClass(node, 'example-leave'); CSSCore.removeClass(node, 'example-leave-active');

What sometimes happens:

  1. transition('leave')

    1.1 CSSCore.addClass(node, 'example-leave') - initiates CSS transition

  2. endListener - transition is finished

    2.1 CSSCore.removeClass(node, 'example-leave'); CSSCore.removeClass(node, 'example-leave-active');

  3. flushClassNameQueue - only then setTimeout timer fired

    3.1 CSSCore.addClass(this.getDOMNode(), 'example-leave-active')

@chenglou chenglou added the addons label Aug 14, 2014

@shilpan

This comment has been minimized.

Show comment
Hide comment
@shilpan

shilpan Sep 9, 2014

@chenglou any updates on this?

shilpan commented Sep 9, 2014

@chenglou any updates on this?

@yurynix

This comment has been minimized.

Show comment
Hide comment
@yurynix

yurynix Sep 23, 2014

Encountered the same issue =\
@victor-homyakov You found any workaround?

yurynix commented Sep 23, 2014

Encountered the same issue =\
@victor-homyakov You found any workaround?

@victor-homyakov

This comment has been minimized.

Show comment
Hide comment
@victor-homyakov

victor-homyakov Sep 23, 2014

Contributor

Manual patching of those places where the classes are added/removed helped to some extent, but not completely. The algorithm of the addon should be rewritten to avoid using both event observers and timeouts simultaneously, but this requires some amount of time. Taking in account other issues easier was not to use this addon at all.

Contributor

victor-homyakov commented Sep 23, 2014

Manual patching of those places where the classes are added/removed helped to some extent, but not completely. The algorithm of the addon should be rewritten to avoid using both event observers and timeouts simultaneously, but this requires some amount of time. Taking in account other issues easier was not to use this addon at all.

@dubert

This comment has been minimized.

Show comment
Hide comment
@dubert

dubert Sep 29, 2014

I have also encountered this issue with multiple DOM objects (20+) listening after a fast sequence of changes.

dubert commented Sep 29, 2014

I have also encountered this issue with multiple DOM objects (20+) listening after a fast sequence of changes.

@cirocosta cirocosta referenced this issue in cirocosta/react-piano-tiles Oct 24, 2014

Open

Does not work on ipad/safari #3

@lsvx

This comment has been minimized.

Show comment
Hide comment
@lsvx

lsvx Nov 4, 2014

I am seeing a similar issue as well. Sometimes, React does not always eliminate the enter and enter-active classes. In this case, transitioning to a different element will result in the former element remaining in the DOM.

lsvx commented Nov 4, 2014

I am seeing a similar issue as well. Sometimes, React does not always eliminate the enter and enter-active classes. In this case, transitioning to a different element will result in the former element remaining in the DOM.

@koistya

This comment has been minimized.

Show comment
Hide comment
@koistya

koistya Dec 7, 2014

Contributor

+1 Just have bumped into the same issue.

Contributor

koistya commented Dec 7, 2014

+1 Just have bumped into the same issue.

@vmakhaev

This comment has been minimized.

Show comment
Hide comment
@vmakhaev

vmakhaev Dec 8, 2014

+1 Any chances that it will be fixed?

vmakhaev commented Dec 8, 2014

+1 Any chances that it will be fixed?

@koistya

This comment has been minimized.

Show comment
Hide comment
@koistya

koistya Dec 8, 2014

Contributor

I was able to solve it by tweaking the order of state variables applied to the component's state. E.g.:

this.setState(updateAB) --> this.setState(updateA); this.setState(updateB);

Contributor

koistya commented Dec 8, 2014

I was able to solve it by tweaking the order of state variables applied to the component's state. E.g.:

this.setState(updateAB) --> this.setState(updateA); this.setState(updateB);

@jmarr

This comment has been minimized.

Show comment
Hide comment
@jmarr

jmarr Dec 13, 2014

I've been running into this issue too. Usually with enter and enter-active not being removed as @lsvx mentioned.

jmarr commented Dec 13, 2014

I've been running into this issue too. Usually with enter and enter-active not being removed as @lsvx mentioned.

@jmarr

This comment has been minimized.

Show comment
Hide comment
@jmarr

jmarr Dec 13, 2014

I just played around with Khan Academy's TimeoutTransitionGroup. I still see animation glitches occur, but the components do get correctly removed, so at least it prevents my app from getting stuck in a broken state.

jmarr commented Dec 13, 2014

I just played around with Khan Academy's TimeoutTransitionGroup. I still see animation glitches occur, but the components do get correctly removed, so at least it prevents my app from getting stuck in a broken state.

@guillaume86

This comment has been minimized.

Show comment
Hide comment
@guillaume86

guillaume86 Dec 15, 2014

I have a similar issue, it happens when changing the cssClass property of an element during his transition.

I have a similar issue, it happens when changing the cssClass property of an element during his transition.

@mfunkie

This comment has been minimized.

Show comment
Hide comment
@mfunkie

mfunkie Dec 19, 2014

Contributor

+1 getting rid of a nice animation to fix this bug in our code :-/

Contributor

mfunkie commented Dec 19, 2014

+1 getting rid of a nice animation to fix this bug in our code :-/

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Dec 19, 2014

Member

I tweaked Khan Academy's TimeoutTransitionGroup to avoid another problem. Maybe it also fixes this problem, so give it a try!

Here's my version:

https://gist.github.com/gaearon/f18a33e3bd58275762f4

Member

gaearon commented Dec 19, 2014

I tweaked Khan Academy's TimeoutTransitionGroup to avoid another problem. Maybe it also fixes this problem, so give it a try!

Here's my version:

https://gist.github.com/gaearon/f18a33e3bd58275762f4

@solussd

This comment has been minimized.

Show comment
Hide comment
@solussd

solussd Dec 24, 2014

+1 breaks all my things. :/

solussd commented Dec 24, 2014

+1 breaks all my things. :/

@henrik

This comment has been minimized.

Show comment
Hide comment
@henrik

henrik Dec 27, 2014

Contributor

Just saw the same issue. React (with addons) v0.12.2.

I have a form that adds things and a table that should list the last 5 things (with animation). If I add many things quickly it will sometimes list more than 5, with the foo-enter and foo-enter-active classes remaining on the surplus elements.

Contributor

henrik commented Dec 27, 2014

Just saw the same issue. React (with addons) v0.12.2.

I have a form that adds things and a table that should list the last 5 things (with animation). If I add many things quickly it will sometimes list more than 5, with the foo-enter and foo-enter-active classes remaining on the surplus elements.

henrik added a commit to henrik/bidtoy-react that referenced this issue Dec 27, 2014

@bitplanets

This comment has been minimized.

Show comment
Hide comment
@bitplanets

bitplanets Jan 14, 2015

+1 I have this sometimes. (take a look at https://github.com/ccoenraets/pageslider-react it might solve some issues)

+1 I have this sometimes. (take a look at https://github.com/ccoenraets/pageslider-react it might solve some issues)

@tommoor

This comment has been minimized.

Show comment
Hide comment
@tommoor

tommoor Feb 7, 2015

Same issue here, it does seem to be related to changing the classes on an item that is transitioning. Simply adding another element within the transitioning item and changing classes on that fixes the issue.

tommoor commented Feb 7, 2015

Same issue here, it does seem to be related to changing the classes on an item that is transitioning. Simply adding another element within the transitioning item and changing classes on that fixes the issue.

@Efimster

This comment has been minimized.

Show comment
Hide comment

+1

@andrelevi

This comment has been minimized.

Show comment
Hide comment
@andrelevi

andrelevi Feb 17, 2015

+1 causing issues on iOS for me.

+1 causing issues on iOS for me.

@mfunkie

This comment has been minimized.

Show comment
Hide comment
@mfunkie

mfunkie Feb 17, 2015

Contributor

If it really is the issue that @tommoor discussed, it might be a good idea to add that to the docs to tell users to wrap their components with variable classes.

Contributor

mfunkie commented Feb 17, 2015

If it really is the issue that @tommoor discussed, it might be a good idea to add that to the docs to tell users to wrap their components with variable classes.

@caedes

This comment has been minimized.

Show comment
Hide comment
@caedes

caedes Mar 18, 2015

@jmarr thx! TimeoutTransitionGroup fix all of my issues.

caedes commented Mar 18, 2015

@jmarr thx! TimeoutTransitionGroup fix all of my issues.

@yakunichevaleksandr

This comment has been minimized.

Show comment
Hide comment
@yakunichevaleksandr

yakunichevaleksandr Mar 20, 2015

+1 causing issue, when changing browser tab

+1 causing issue, when changing browser tab

@leiserfg

This comment has been minimized.

Show comment
Hide comment
@leiserfg

leiserfg Mar 23, 2015

@caedes it works for me too!

@caedes it works for me too!

@sophiebits

This comment has been minimized.

Show comment
Hide comment
@sophiebits

sophiebits Apr 1, 2015

Member

Merging into #1326, but it sounds like TimeoutTransitionGroup is working for most people.

Member

sophiebits commented Apr 1, 2015

Merging into #1326, but it sounds like TimeoutTransitionGroup is working for most people.

@aluksidadi

This comment has been minimized.

Show comment
Hide comment
@aluksidadi

aluksidadi Jul 22, 2015

this error transition(): tried to perform an animation without an animationend or transitionend event after timeout (5000ms). You should either disable this transition in JS or add a CSS animation/transition. happened to me when i have other css classes in the child element that are animated.

after i removed those other css classes it worked properly.

i dont know if those other css classes were the issues, but i just want to point this out here.

this error transition(): tried to perform an animation without an animationend or transitionend event after timeout (5000ms). You should either disable this transition in JS or add a CSS animation/transition. happened to me when i have other css classes in the child element that are animated.

after i removed those other css classes it worked properly.

i dont know if those other css classes were the issues, but i just want to point this out here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment