React Native 0.85 changelog dive
09 April 2026 · 9 min read

React Native 0.85 changelog dive

Let's explore what's interesting in the React Native 0.85 release, from Shadow Tree commit branching to the new Animation Backend.

Introduction

Every React Native release ships with a long changelog, but most of us just scan for breaking changes and move on. That’s a missed opportunity. The changelog is a window into where the framework is heading, and 0.85 is one of the most exciting releases in recent memory.

As someone who maintains two libraries that commit directly to the Shadow Tree (Uniwind Pro and Unistyles), I read every line of the 0.85 changelog with a very specific question in mind: what’s going to break, and what new doors does this open?

In this post, I’ll walk you through the changes that caught my eye and share how they affect (or will affect) our libraries.

Let’s dive in!

Shadow Tree commit branching

If I had to pick one change that defines this release, it would be the new Fabric commit branching mechanism introduced by @j-piasecki. It spans four connected PRs (#54833, #54835, #54836, #54837) and fundamentally changes how React Native commits updates to the Shadow Tree.

So, what was the problem?

Before 0.85, every commit (whether from React or from native sources like animations) updated the same _currentRevision__ directly. This meant that when Uniwind Pro’s C++ engine pushed style updates to the Shadow Tree at the same time as React committed a state change, they were fighting over the same revision. This created contention between the JS thread and the main thread, leading to potential race conditions and resource exhaustion during intensive update cycles.

The new approach introduces dual branching:

Here’s the key detail from the PR description: “merge” means taking the JS revision and promoting it to become the new main, losing changes that happened on the main branch between fork and merge. Preservation of these changes is the responsibility of the party that created them, and they should be reapplied using a commit hook.

The merge is scheduled on the main thread, which prevents Shadow Tree exhaustion since all main branch commits now happen on the same thread.

This feature is gated behind the enableFabricCommitBranching feature flag. It’s not enabled by default yet, but the infrastructure is in place and ready for testing.

What does this mean for Unistyles and Uniwind Pro?

Both libraries commit style updates directly to the Shadow Tree from C++. With this branching model, our commits land on the main branch (we’re “other sources”, not React). React’s commits go to the JS branch. So far so good, no contention between the two.

But here’s the catch. When the JS revision merges, it replaces the main revision entirely. Any changes we committed to the main branch between fork and merge are lost. The PR is explicit about this: libraries must use a commit hook to reapply their changes after the merge.

Uniwind Pro already uses a commit hook (that’s how we persist style overrides across React re-renders), but we need to make sure our hook correctly reapplies styles after the new JS revision merge, not just after regular React commits. I’ll be testing this extensively once the flag is enabled by default. If your library also commits to the Shadow Tree from native code, keep this in mind.

Animation Backend is now the default

The second major change is that the C++ Animation Backend is now enabled by default. Previously, this was behind the -DRN_USE_ANIMATION_BACKEND compiler flag. Now it’s an integral part of every React Native build.

What exactly is the Animation Backend?

It’s a part of the React Native renderer that enables animation frameworks to update props of React components without going through React’s JavaScript rendering pipeline. Instead of animation-based commits fighting for the Shadow Tree alongside React and styling libraries, the Animation Backend moves them to a separate, dedicated mechanism.

The backend works through a few key components:

Animation frameworks register callbacks via the start method, which returns a CallbackId. On each animation frame, the callback receives an AnimationTimestamp and returns a list of AnimationMutations, each pairing a ShadowNodeFamily (which component to update) with its new props. The stop method takes the CallbackId to cancel, and trigger fires synchronous updates for events like gestures.

What’s particularly interesting is how it synchronizes with React. The AnimationBackendCommitHook restores overridden properties during React commits, ensuring that animated values aren’t accidentally reset when React re-renders a component.

usage.cpp
// start() takes a callback, returns a CallbackId
auto id = backend->start([](AnimationTimestamp timestamp) -> AnimationMutations {
    // Return mutations: which components + what props
    return {
        .batch = {{
            .tag = viewTag,
            .family = shadowNodeFamily,
            .props = animatedProps,
            .hasLayoutUpdates = false,
        }},
    };
});

// Stop by ID when animation completes
backend->stop(id);

There’s also a new mechanism where Animated can prompt the backend to push changes to the Shadow Tree on the JS thread. When animations complete, a scheduled commit is performed to force the commit hook to push updated ShadowNodes to React through RSNRU. This ensures React’s renderer receives the final state of animated values.

This is the change I’m looking forward to the most. Right now, multiple libraries (Reanimated, Unistyles, Uniwind Pro) all commit to the Shadow Tree independently, and they can override each other. Moving animation commits to a separate mechanism is a step toward deterministic Shadow Tree updates, where each party has a well-defined path for applying changes without stepping on each other’s toes.

Software Mansion is working on streamlining this approach with Reanimated. Once the Animation Backend ships with no flags from React Native 0.85.1, I’ll explore how Uniwind Pro and Unistyles can benefit from the same infrastructure. If we can eventually converge on a shared mechanism for non-React Shadow Tree updates, it would solve a whole class of subtle bugs that library authors deal with today.

Bartlomiej Bloniarz from Software Mansion is the main author behind most of the Animation Backend changes in this release. His work on the choreographer, mutex safety, and the AnimatedPropsRegistry cleanup is impressive. If you’re curious, check out the RNTester examples he added for the Animation Backend.

cloneMultiple API change

This one directly affects us. The cloneMultiple method now requires std::shared_ptr<const ShadowNodeFamily> instead of raw pointers. The commit explains why: when views unmount, the held ShadowNodeFamily shared_ptr can be deallocated, leaving dangling raw pointers.

This was specifically triggered by the Animation Backend. Reanimated holds references to ShadowNodes, so the old raw pointer approach worked for them. But the Animation Backend doesn’t hold the same references, and views can unmount while animations are still running.

Both Unistyles and Uniwind Pro use cloneMultiple to batch style updates across multiple components. We’ll need to update our C++ code to pass owning shared_ptr instances. The fix is straightforward, but if you’re a library author using this API, don’t miss it.

StateWrapper in fbjni

A small but meaningful change for native module authors: @mrousavy added StateWrapper to C++ fbjni types.

Previously, if you were building native views with Fabric and needed to work with state in C++ (through frameworks like Nitro Modules), you had to define your own StateWrapper implementation and perform unsafe downcasting. Now, the official StateWrapper base class is exposed through fbjni, enabling type-safe inheritance and proper jni::dynamic_ref_cast instead of unsafe static casts.

This is great for the ecosystem. The fewer unsafe casts we all maintain, the fewer mysterious crashes our users report.

View Transition feature flag

A new feature flag called viewTransitionEnabled landed in 0.85. It gates a View Transition API that enables animated transitions between views. Think smooth navigation transitions and UI element updates.

The flag is false by default, so this is purely infrastructure for a future release. But it’s worth keeping an eye on. In Uniwind Pro, we already ship animated theme transitions (circle reveals, blurs, fades). If React Native introduces its own View Transition API, we could potentially leverage it to make our theme transitions even smoother and more integrated with the platform.

Text rendering changes

A subtle but important visual change: text outside the bounds of a borderRadius is now hidden by default.

Before 0.85, Text components defaulted to overflow: visible, which meant text could be drawn on top of borders and extend beyond borderRadius bounds. The native implementation was inconsistent, mixing hidden and visible overflow behaviors.

Now, text is clipped to the padding box by default. This provides consistency between Fabric’s style layer and native platform behavior. If your app relied on text overflowing rounded corners (intentionally or not), you may need to explicitly set overflow: ‘visible’ on those components.

For Uniwind and Unistyles users, this shouldn’t require any library-side changes. It’s a React Native rendering behavior, and our style engines will pass through whatever overflow value you set.

Other breaking changes

StyleSheet.absoluteFillObject is gone. It was deprecated in 0.82, and now it’s removed. Use StyleSheet.absoluteFill instead:

Migration.tsx
// Before
const style = { ...StyleSheet.absoluteFillObject };
const style = { ...StyleSheet.absoluteFill };

Yoga migration to Kotlin

Another interesting change: YogaNode, YogaConfigJNIBase, and YogaProps have all been migrated to Kotlin by @mateoguzmana. This is part of a larger effort to modernize React Native’s Android codebase. It shouldn’t affect behavior, but it makes the Yoga integration more accessible for Android developers who prefer Kotlin over Java.

Summary

I’m genuinely excited about this release. It might take a few months for everything to land without feature flags, but the direction is clear and the impact on Unistyles and Uniwind Pro will be huge.

The Shadow Tree commit branching gives us a cleaner model for native-side updates. The Animation Backend moving to a separate mechanism opens the door to deterministic Shadow Tree commits across libraries. Together, these changes could unlock entirely new patterns for us: style-driven animations, shared element transitions, or other features that today require fighting the renderer instead of working with it.

I’ll be covering the Animation Backend in much more detail in a future post. Stay tuned!

Happy coding! 🎉