react-native-reanimated: [ios][bug] Huge issue with LayoutAnimation - Single `Animated.View` with `layout` prop is enough to break un-mounting and de-allocation of any View which has been popped/swiped-back/closed/destroyed via navigation
Description
I have found a serious bug with LayoutAnimation. I have been trying to investigate the problem for several days, which is why videos that were in a screen or modal that I closed (goBack/pop/swipe to dismiss) still played even though everything was un-mounted and destroyed. The same is true for cameras (Green Light Indicator is no longer out).
It is sufficient to have a single Reanimated.View
/ createAnimatedComponent
ANYWHERE in the app which uses layout, entering or exiting
prop from Reanimated. Once a single View
with that prop has been mounted (no matter where), no element that is in a navigation stack will be unmounted anymore, even if the layout hierarchy and lifecycle methods reports that it has been unmounted (eg cleanup function of useEffect
). When you remove something conditionally on the screen (eg. with useState
), un-mounting works fine. But it looks like a single use of LayoutAnimation
is enough to break element un-mounting / de-allocation when closing Navigators, because (this is my guess) LayoutAnimation is still “watching all of them (or snapshotting?)” in order to be able to animate the layout, even when those views are in different screens. Maybe RNS is also an issue here?
I also did some tests, such as setting breakpoints at the deallocate function of expo-av. The methods were never called when layout, entering
or exiting
were present and mounted anywhere in the app. But if no Reanimated.View
with layout
was used the breakpoints triggered.
I have also created a video as well as a repro which can be tested with Expo Go.
Expected behavior
Views should correctly un-mount and deallocate once a Navigation screen has been dismissed / popped etc, even when using LayoutAnimation
.
Actual behavior & steps to reproduce
To test my findings, simply grab my repro, spin it up, open Tab One and tap on the info icon at the top (headerRight) - as many times as you like. The video will start and stop as soon as the modal has been closed. But if you now switch to Tab two, which mounts a Reanimated.View
with layout={Layout}
, (imported from REA) and you now simply return to Tab one, you will notice that the video will continue to run as soon as you open and close the modal and it will start multiple videos until the App crashes eventually. If you remove layout
from Tab two, you can open and close the modal 1000x and it will work fine. Please note that you need to restart the app when you add or remove layout
, fast-refresh is not enough.
I provided a repro and all informations in my issue + in my repro App as Text
.
Here is also a Video showing the issue (watch with audio please)
Watch with audio
https://user-images.githubusercontent.com/504909/161172649-3d2b600d-41fb-47ec-87bd-89c69f55fe15.mp4
Snack or minimal code example
https://github.com/hirbod/react-reanimatad-layoutanimation-bug
And this single layout
prop is enough to trigger the issue (once mounted):
https://github.com/hirbod/react-reanimatad-layoutanimation-bug/blob/main/screens/TabTwoScreen.tsx#L7
Package versions
name | version |
---|---|
react-native | 0.64.3 |
react-native-reanimated | 2.5.0 (but breaks with any version that has LayoutAnimation) |
Xcode | 13.3 |
expo | SDK 44 |
Affected platforms
- Android
- iOS
- Web
Here is a cross link to RNS, since I am not sure if RNS or REA is the root issue: https://github.com/software-mansion/react-native-screens/issues/1379
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 48
- Comments: 69 (22 by maintainers)
Good news, I found the cause of the issue today and I know how to resolve it.
@hirbod Hey, I have just started to investigate it. This is a priority issue, I will notify you about progress.
It seems like there is no activity in the rewrite branch since early July. We basically cannot use layout animation in its current state and I suspect many are in the same situation. Is there any workaround we can do to be able to use layoutanimation until a rewrite/fix is out?
is there any news with that ?
We need to clearly distinguish between all the other errors reported here:
https://github.com/software-mansion/react-native-reanimated/issues/3093 Duplication of Nodes, especially when react-native-svg is used.
All of this might be related or be isolated issues.
Thank you so much for posting this, we have been racking our brains at why all kinds of random things in our app stopped working when we implemented reanimated v2 layout anims (images, svgs, other animations, etc). As soon as we remove the entering/exiting props across the application everything works as normal.
Weirdly enough in our case iOS is not affected but Android is. This is a massive blocker for us, anyway we could get some eyes on this when you guys have some time? @j-piasecki
FYI: Reanimated V3 RC6 includes the all new LayoutAnimation rewrite. I think its time to close this issue, right @piaskowyk ? 😃
In case you guys asking: when your codebase does not make use of any Rea1 functions, its safe to upgrade to Rea3 (its Rea2 with Fabric support but works also with the old architecture). If you can’t upgrade to REA3 because of Rea1 legacy libraries, you’ll have to wait. The rewrite will be backported to v2 soon.
This issue was long lasting but pretty complex. But you’re not only getting a stable LayoutAnimation, you’re getting SHARED ELEMENTS with react-native-screens - NATIVE. Thanks a ton to everybody involved in this.
Hello 👋 any news on this ? I’m facing this issue with version 2.8.0 on iOS 15.5 (RN version 0.66.4).
@piaskowyk thank you very much! Appreciated.
I am facing the same issue like when we use entering/exiting/layout prop from reanimated V2 some of the ui views goes invisible. Thanks for investigating this and bringing this up as this is hard to debug and find the root cause. When I commented all entering/exiting/layout props, it works perfectly. A huge blocking for our case as we added many animations and now this adds visibility issue for other UIs. Also, this is for android only in my case In my case somehow when I use any of entering/exiting/layout props, zindex/layering is done wrongly on newly mounted screen , so my invisible ui were behind some fullscreen ui. (I temporarily fixed by reordering component sequence but ideally reanimated should not touch zindex/layering) It would be great if someone can look into this.
@hirbod LayoutAnimations with V3 RC6 seem even more broken. I get screen corruption and frozen UI as soon as layout animations are enabled. I haven’t filed an issue yet, but wondering if anyone else is seeing this with RC6
have you tried to add
from react-native-screen
@hirbod #2906 provides an android repro for the android issues reported here, but it seems like a separate issue to what is being addressed in PR #3157.
@hirbod thank you for digging into this. I was so lost when i had this exact issue with a video.
Glad that my findings helped you. I searched 15 hours without sleep until I found the root cause (I was THIS close to switch RNS to RNN because I was out of ideas. It was a lucky find at the end and never have I ever thought that reanimated could be the cause 😅 )
I did not encounter bugs on Android though, at least in my specific scenarios, everything was working fine. I only did use LayoutAnimation on two FlatLists and a couple of buttons. What hurts the most is my beautiful TextInput animation. I hope I don’t have to remove LayoutAnimation and they will be able to fix the issue soon.
I think it would be helpful if you guys could also provide a failing repro on Android, this might help to get both issues resolved.
@dFelinger I think you missed this:
@hirbod glad to read it 😊
The time has come. After testing REA 3 very intensively, I take a bow and say thanks to everybody involved!
@Osebrian The rewrite shipped with one of the minor versions of Reanimated 3, so you’re all good now.
Cant use the functionality at all until this is fixed
For me, all I need to replicate is just an
No need to render any Animated.View. When I go to any screen and go back (by navigation back, or programmatically navigation.goBack()), the screen is not responding to touch/scroll. The screen is still functioning properly, but you simply can’t do anything. No error, no log, nothing. When I inspect the layout, there’s no component on top covering below.
Because the problem occurs when navigating and react-navigation does use react-native-reanimated, so I think it’s incompatibility with react-navigation. This is a serious blocking issue.
Using 2.8.0, layout animation is very laggy on Android, while the following error is thrown on iOS.
This issue here is for iOS (which some reports for Android as well)
@iway1 don’t migrate. See if the new layout rewrite fixes your issues.
waiting for resolve 😦(
@hirbod Big thanks for documenting this issue, had my head wrapped around this issue combined with react native video lib.
Currently, our team just removed all instances of LayoutAnimations and now react native video player instance removes itself on back navigation.
Waiting to see if that rewrite fixes the issue.
@ShadReyes you’re referring to react-native core LayoutAnimations, has nothing to do with the one by reanimated
It does not work. I’ve tried every combo of
enableScreens()
andenableLayoutAnimations()
to no avail. Just adding an animated view with an entering prop ANYWHERE will break it. It’s VERY frustrating and seems to be a rather large problem. Is there any headway on this???Had this same issue for a long time.
Importing and calling
enableLayoutAnimations
inApp.tsx
fixed it for meRelated isssue: https://github.com/software-mansion/react-native-reanimated/issues/2758
It is not resolved @michbil, LayoutAnimation is currently getting a rewrite
LayoutAnimation is undergoing a rewrite, since fixing this issue seems to be something bigger. I think parts of it are cpp, so chances might be that they will fix issues on android as well - but I have no deep knowledge about that. There haven’t been any acknowledgments towards android so far, there are also some pretty annoying scrollview issues (android only) going on with reanimated.
Following up here as we have reproduced what @hirbod initially reported. Our iOS app is affected by an RTMP stream never releasing even when unmounted, similar problem to what is displayed in the reproduction. Commenting out layout props resolves the issue as well.
We can still try to reproduce the zIndex hierarchy issue in a repo if necessary. We’ve spent a whole pile of time debugging all these issues so reproduction has been a little delayed so far
I mean, there are alternatives, like https://moti.fyi which use reanimated under the hood without LayoutAnimation (but be careful, they also added support for LayoutAnimation from REA as well if you would like to use it). Its pretty straightforward to animate (also entering/exiting) with AnimatePresence, but there is no comparison to LayoutAnimation (specially how easy it is to use).
The issue is severe imho, I think the feature is just “too new” and not adopted widely enough. Thats why nobody had complaints so far. And I think its pretty hard to find the root cause when things start acting weird (like elements not un-mounting). I would’ve been curious if I had a LayoutAnimation on a
Video
, but for me it was a Button inside an invisible (but mounted) tab.@LeviWilliams feel free to copy my repro to create your case with android.