react-flip-move: On chrome mobile after 2 animations with many leaves then react-flip-move gets stuck in state where many nodes hang about that should have been removed.
Using a recent version of mobile chrome go to kchomp.co and touch the worldnews
link at the top followed by the news
link as quickly as possible.
From here if you click the worldnews
link again you should see that a bunch of the nodes related to news
remain in the DOM. I verified with remote debugging that these nodes are no longer in props.children
. From here clicking further links in the header leads to more and more HTML elements being left around. It seems that react-flip-move
has gotten into a state where it can no longer remove needed elements.
I have been unable to replicate the issue on desktop chrome, it seems specific to mobile chrome. Using the latest react-flip-move (2.7.3
).
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 4
- Comments: 53 (13 by maintainers)
There is a chance it could be solved if we would store styles in state and pass it to react children instead of applying directly. In that case the styles would be preserved during rerender. But this would mean a breaking change as it would require all children to accept
style
prop.@cusspvz interesting… we’d also have to merge with any existing styles, but that’s an easy-to-solve nit.
Would be receptive to giving this a shot 😃 my schedule’s crazy right now, involved in a couple other projects and very busy at work, but I think this is a problem worth fixing and storing styles in state seems to make sense to me (I’d have to think much more about it to know if there would be unintended side effects).
@joshwcomeau thanks for your replies. I fiddled some more into the problem and found the cause of the problems.
My example from above: https://github.com/joshwcomeau/react-flip-move/blob/master/src/FlipMove.js#L106 shows how items stay in the DOM because of
transitionend
not being called. Notice how I am using the “fade” for the animations:However, it appears that when using an the default transition (elevator) my example does not break! All the
transitionend
are fired normally.And this is where it gets troublesome. It seems to be related to whether the item is “moving on the screen” whether the
transitionend
is actually fired.Only when we are using Elevator (fade, accordionHorizontal, accordionVertical all break)
the items that are being added 1 by 1 all continue their move but all jump to a opacity(1) / scale(1)-size-wise. The reason why we see the items move with the ‘elevator’ animation is because of the scale transition (atleast thats the case in my example). The scale animation apparently somewhat continues (although bugged) and at least fires the
transitionend
event.This means that the CSS Transitions (at least in my chrome version) are falsely animating the transition when the component is being re-rendered. On top of that, the
transitionend
is fired only if something moves on the screen.To be 100% sure of my theory I tweaked the animations with a little hack and gave them all a
transform: translate(0.001px,0)
from which they start. This should not be visible on the screen but it tricks Chrome into thinking the items are being moved.The result? All the
transitionend
events are fired and no items get stuck in the DOM because of this. All in all this reminds me of the sad IE6 days 😦.The question is where to go from here. I think my hack could atleast solve FlipMove from breaking completely when adding/removing items quickly but it’s still sad that the transitions aren’t fully visible when the component gets re-rendered. I wonder what exactly FlipMove/React is doing with the DOM whenever a render is called. To me it seems like the transitions shouldn’t break if the DOM of the transition item isn’t touched at all.
I dumped the code I’m using here for now: https://github.com/ohjames/react-flip-webanimate I’ll add some docs and make it more generic someday soon, maybe.