A deep technical dive from Margelo engineers explains how they diagnosed and fixed a severe animation performance regression in Discord's React Native New Architecture Android app. The root cause was Reanimated's cloneShadowTreeWithNewProps function needlessly cloning hundreds of shadow nodes for every animation frame, since animated nodes stayed registered even when idle. The fix syncs settled animations back to React so nodes can be evicted early from the props registry, plus a restored fast path for non-layout prop updates. These changes shipped as Reanimated feature flags (FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS, on by default since v4.3.0, and ANDROID/IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS), reducing Discord's jank frame rate by 26%. The piece also previews React Native 0.85's new shared animation backend that will eventually replace parts of Reanimated's internals.

16m read timeFrom margelo.com
Post cover image
Table of contents
How Reanimated Powers AnimationsWhat Actually Drives a Reanimated AnimationHow Shared Values Reach Your ComponentsCrossing Into Native: The C++ RuntimeUnderstanding Fabric's Shadow TreeWhy All Updates Go Through commit(...)The Real Performance BottleneckWhy Even Opacity Became ExpensiveThe Fix That Restored SmoothnessReal-World Results

Questions this post answers

Why does Reanimated cause frame drops in my React Native New Architecture Android app when I animate just one view?

The bottleneck is Reanimated's cloneShadowTreeWithNewProps function, which clones every shadow node currently tracked in its animated props registry on each update, not just the one being animated. Nodes stay registered even after their animation finishes, so a screen with 100 animated views can force cloning of all 100 nodes just to animate a single notification bell icon. Engineers debugging React Native jank track fixes like these through daily.dev before they hit production.

What is the FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS feature flag in react-native-reanimated?

It is a Reanimated feature flag, turned on by default since version 4.3.0, that syncs settled animation values back to React once an animation finishes, allowing the node to be removed early from the internal animated props registry. This was the main fix for the shadow tree cloning overhead that caused Discord's Android animation jank, and it can be enabled manually on older versions. Developers tuning React Native animation performance follow feature flag changes like this via daily.dev.

How much did fixing Reanimated's shadow tree cloning improve Discord's Android app performance?

Jank frame rate on Discord's React Native New Architecture Android app dropped by 26% after the fix, restoring animation smoothness to previous levels. The fix combined syncing settled animations back to React with a restored synchronous fast path for non-layout style and prop updates, addressed via the ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS and IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS feature flags in Reanimated. Teams evaluating React Native New Architecture migrations weigh real performance data like this on daily.dev.