-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Architecture - "Sticky" list header flickering when using useAnimatedScrollHandler
/useAnimatedStyle
#6992
Comments
We've tried patching this change in, but still experiencing the repro. |
Here's what I found out so far:
|
After some digging with @bartlomiejbloniarz, we found out that the solution is to enable |
@tomekzaw How can I enable this feature flag? Also what does it do? I am not able to find any documentation about it. Also for me there is significant framedrop on both threads when doing similar animation when scrolling fast. Since it drops frames also on UI thread it will cause scroll itself to be janky. |
Probably the easiest way is to just return
When
Reanimated intercepts As for state update, React Native synchronously calls
We've noticed that there's a feature flag that changes the behavior |
@tomekzaw Thanks for exhausting explanation! Do you know what's the reason that this is not enabled by default? Using own modified version of RN isn't really comfortable. |
@Nodonisko I don't know the exact reason, I suspect that some of the changes in the rendering pipeline are hidden behind a feature flag so the community can test it on a small group of users and prevent unwanted regressions. |
Thanks, so to sum it up we either can use our local version of RN with feature flag turned on or wait until it will be on by default in RN. |
## Summary This PR adds an example with sticky header implemented using `useAnimatedScrollHandler` (although `useScrollViewOffset` is also recommended) and `useAnimatedStyle` to align the vertical translation of a view with `ScrollView` content offset. Source code has been adapted from the repro in #6992 by @Flewp. ## Test plan
@Nodonisko Did this solution work for you? Unfortunately didn't help in my case. Tried on RN Versions: 0.76.7, 0.77.0 |
@jonatan-zoominfo Sadly no, currently I only disabled animation for Android because it's not critical for us. |
This issue reproduces also with sticky headers in @shopify/flash-list which are implemented without reanimated and greatly affects scrolling performance (on production builds as well). Reproducing also on on ios. withReanimated.movwithoutReanimated.moviosWithReanimated.mov |
I've done further investigation here to try to find the root cause of the issue. It seems to boil down to how animated props are added in Here's more details about what happens exactly: On iOS, the renderer implements what we will call here a "pull" model. What this means is that when react is done mutating the shadow tree it notifies the mounting layer, which will then post a new task to be executed on the UI thread. This task will then "pull" the mutations from the shadow tree and commit them to the host views synchronously. This is very important since this guarantees that what is committed represents the latest state of the shadow tree. ![]() You can see here that since the operations are pulled from the UI thread, they do include updates that were committed from the ui thread. On android, the renderer implements what we will call here a "push" model. What this means is when react is done mutating the shadow tree it immediately pulls the mutations and posts a new task to be executed on the UI thread containing the mutations. The UI thread will then commit these updates to the host views. Note that if an update is committed from the UI thread after the mutations were pulled from JS, it is possible that stale values will be committed. ![]() In this case, here's what happens: ![]() It also happens a lot more because scroll events trigger native state updates, which are also dispatched from the JS thread (without the synchronous state updates feature flags) and trigger the commit hook. However just using sync state updates doesn't fully solve the issue since JS updates from react renders will also trigger the same problem. I think the ideal fix is to implement the same pull model on Android as we have on iOS, but this might require a lot for work. I am curious if there is any workarounds we could implement in reanimated in the meantime. |
@janicduplessis Thank you for the explanation. Do your investigation results relevant considering that this issue also reproduces on ios? See my previous comment. |
In our case we didn’t see any problems on iOS, and also not using flashlist, I suspect this might be a different issue. |
Description
I have a
ScrollView
that contains an item that I want to "stick" to the top. Historically we've given this sticky item auseAnimatedStyle
where itstransformY
is driven by a shared value that is updated by auseAnimatedScrollHandler
attached to theonScroll
property of theAnimated.ScrollView
. This works using the old architecture, but in the new architecture the sticky item lags behind the scroll view's offset, causing the sticky item to flicker.old-arch-video.mov
new-arch-video.mov
Steps to reproduce
Reproducer link is below, or use this component in a sandbox app.
Snack or a link to a repository
https://github.com/Flewp/reanimated-scroll-reproducer
Reanimated version
3.16.7
React Native version
0.77.0
Platforms
Android
JavaScript runtime
Hermes
Workflow
React Native
Architecture
Fabric (New Architecture)
Build type
Release app & production bundle
Device
Real device
Device model
Pixel 7 Pro
Acknowledgements
Yes
The text was updated successfully, but these errors were encountered: