React-native-reanimated: onScroll events and performance

Created on 3 Jan 2019  路  18Comments  路  Source: software-mansion/react-native-reanimated

Hi! Thanks for an interesting library!

I have been playing around with using reanimated to build an header that tracks a scrollview (or flatlist maybe) and have encountered some performance issues I can't figure out.

An example of this can be seen in this snack: https://snack.expo.io/rkT2_e3Z4

On device (iPhone X, iOS 12.1.2) I can see the following:

  • When scrolling up and down quickly, it looks like the header tracks one or a few frames behind the
    list.
  • When momentum scrolling from the bottom of the list to the top, the header is "stuttering" a bit.

As I add more things to the header these issues become more apparent and it just does not look good. Using the Animated library from react-native gets rid of these issues, but then there are some nice things I can't do that reanimated could solve :) Is there anything wrong in my code, or any way of getting rid of these issues?

Thanks!
Micke

Most helpful comment

Did some digging into this and it seems to be related to iOS optimization and the reanimated scheduler. Due to most battery optimizations not being active in the simulator this problem is most pronounced on a physical device.

The major difference between the RN Core animated implementation and reanimated is that RN will update the nodes for each _scroll event_, and avoids too frequent updates by throttling the event itself. Reanimated on the other hand will accept and queue all events and ask the OS for an animation frame. That means reanimated is always at least one frame behind, which can be illustrated by scrolling up and down quickly where the other view seems to lag behind a bit.

The other factor is that the OS decides how often it call the animation frame callback. It's supposed to do so as often as the frame rate if not specified, although in my findings it seems to also depend on when the OS thinks it's needed. So for example during direct manipulation with the finger, the refresh rate is high (60 FPS), but when the finger is off it's suddenly lowered (to 30FPS).

I'll continue to investigate whether there are some workarounds, but my assumption is that it's going to be hard to get the same no-lag behaviour without also changing the way the scheduling works.

All 18 comments

hello :)
I know I will ne really answer you question but, why not use a FlatVIew ? is support header and footer right out of the box :)

have a look to the doc

here a very nice article about this features

I hope it helps

Thanks @F4b1n0u! I am actually using a FlatList in the real code of the project, but the headers don't do all the things I want them to do in the future. I guess my real question is if there will always be a bit of a delay when tracking things using reanimated. And if the choppy rendering I'm seeing is actually normal. Or if I did something wrong?

Same issue with ScrollView
@osdnk can you help ?)

Hi everyone,
Sorry, I know there're some issues with it. I'll to my best to take a look on it as soon as it's possible, but I cannot promise it will be possible soon for me.

Hey I just stumbled upon this issue as well. Did you make some progress or have any idea why that happens? I also especially notice it during iOS Momentum scroll. I was wondering first if it was related to scrollEventThrottle, but no matter what value it didn't make much of a difference.
In my make case I can't switch to the original Animated to test it because I'm using cond nodes.

@osdnk Hi, any updates about this issue =)? Or can you say where to start research this issue(some place in code) ?) Thank you!

@kmagiera @osdnk Hey! Same as @matpaul I鈥檇 like to help if possible. Driving animations on scroll content offset is super powerful and add Reanimated it鈥檚 pretty much BEAST mode.

I'm also seeing this issue - any progress?

When adding more content into a ScrollView I've been able to get a similar "stutter effect" when using { userNativeDriver: false } when using React Native Animated as when using Reanimated. Is there some JS-side computation that unintentionally gets triggered? Or maybe some layouting computations get triggered by mistake on every frame?

Did some digging into this and it seems to be related to iOS optimization and the reanimated scheduler. Due to most battery optimizations not being active in the simulator this problem is most pronounced on a physical device.

The major difference between the RN Core animated implementation and reanimated is that RN will update the nodes for each _scroll event_, and avoids too frequent updates by throttling the event itself. Reanimated on the other hand will accept and queue all events and ask the OS for an animation frame. That means reanimated is always at least one frame behind, which can be illustrated by scrolling up and down quickly where the other view seems to lag behind a bit.

The other factor is that the OS decides how often it call the animation frame callback. It's supposed to do so as often as the frame rate if not specified, although in my findings it seems to also depend on when the OS thinks it's needed. So for example during direct manipulation with the finger, the refresh rate is high (60 FPS), but when the finger is off it's suddenly lowered (to 30FPS).

I'll continue to investigate whether there are some workarounds, but my assumption is that it's going to be hard to get the same no-lag behaviour without also changing the way the scheduling works.

Hi, it seems it is resolved in iOS, but, what about Android? any plan for this?

Hey @alikazemkhanloo It seem like this exact problem applied only to iOS and the fix from @oblador resolved the issue. What I think is happening in your case is that you may be expiriencing issue with some layout property and not translateY as provided in the repro scenario here.

I tried the repro case on an Android phone and simulator and didn't expirience any lagging when translate is used. If this is the case for you feel free to reopen this issue. If you have problem with some other properties (e.g. layout props as described in #324) please respond on the relevant issues or open a new one.

I'm experiencing same issue on Android, using my own personal phone.
The scroll is jerky when the user scrolls and holds the screen. It works very smoothly though, when the scroll is initiated by a swift swipe without the user still touching the screen.

on iOS I don't see any problems.

@papigers Hey I am facing the same issue, how did you address it ?

Would like an update on this too :) Implemented a screen with a large header and sticky tabs. The tabs "stick" using a translateY and reanimated. On android, when you lift your finger of the screen, the sticky tabs "lag" behind a bit.

Me too

Android fling animation lag also present on emulator

I've created new separated issue for this case #1554

Was this page helpful?
0 / 5 - 0 ratings