
The React Native Animation Performance Secret: Why Your Animations Jank and How Reanimated 3 Fixes It
- Larry Brooks
- Software, Technology
- 25 Jun, 2026
Your list scrolls smoothly — until a background API call completes and triggers a state update. Suddenly, the scroll animation drops from 60fps to 23fps for 200 milliseconds. Your users feel it. Your one-star reviews mention it. And no amount of JavaScript optimization will fix it.
The problem is architectural: your animations run on the JavaScript thread, and they compete with every other JavaScript operation for execution time.
Why the JS Thread Is the Wrong Place for Animations
React Native's JavaScript thread handles business logic, state management, API calls, data transformation, and — if you are using the Animated API with useNativeDriver: false — animation calculations. When any of these operations takes more than 16 milliseconds (the budget for one frame at 60fps), the animation drops frames.
Setting useNativeDriver: true helps for simple transform and opacity animations. But it does not support layout properties (width, height, margin, padding), color animations, or any animation that depends on JavaScript-computed values. For complex animations, the Animated API forces you back to the JS thread.
How Reanimated 3 Solves This
Reanimated 3 runs animation logic on the UI thread using worklets — small JavaScript functions that execute on a separate thread with direct access to view properties. The JS thread can be completely blocked, and Reanimated animations continue at 60fps.
The difference is not subtle. We benchmarked a screen with a parallax scroll header, animated tab bar, and list with item entrance animations. With Animated API: average 41fps during data fetching, dropping to 28fps during heavy state updates. With Reanimated 3: consistent 59-60fps regardless of JS thread activity.
The Migration Path
Reanimated 3 uses a different API than React Native's Animated. The core concepts are shared values (replacing Animated.Value), animated styles (replacing Animated.View style bindings), and worklets (replacing Animated.timing and Animated.spring).
The migration is not a find-and-replace. Reanimated's mental model is different: instead of imperatively starting and stopping animations, you declare how styles derive from shared values, and the UI thread recomputes them automatically.
Start by migrating your most janky animation. Learn the API on one real use case. Then migrate screen by screen, prioritizing animations that users interact with most frequently.
The Gesture Integration
Reanimated 3 combined with React Native Gesture Handler creates a gesture-animation pipeline that runs entirely on the UI thread. A swipe gesture that drives a card dismissal animation — the gesture tracking and the animation response both execute on the UI thread without touching JavaScript.
This is how native apps achieve their fluid gesture interactions. Before Reanimated, React Native could not match it. Now it can — with the right architecture.
When to Use What
Use React Native's built-in Animated API for simple opacity and transform animations where useNativeDriver: true is sufficient. Use Reanimated 3 for layout animations, gesture-driven animations, spring physics, and any animation that must remain smooth during heavy JS thread activity.
If your app's animations stutter and your users notice, let's fix the architecture.
