designer animations that need INTERACTIVITY/state machines, or many Rive views sharing files → Rive; new work goes to the Nitro line @rive-app/react-native (0.4.x, early — pin), not the quiet legacy package
hundreds of concurrently-animating views blowing the frame budget → benchmark react-native-ease (fully native-driven; young)
heavy animation perf → route to react-native-best-practices
Options & tradeoffs
the field considered — and why each one isn’t the default here
option
tradeoff
evidence
Reanimated 4
UI-thread + CSS-style animations/transitions; worklets split into react-native-worklets; requires New Arch
5.6M/wk · ships in 12/34
Gesture Handler 3.0
native gestures; v3 adds a hook-based API built for the React Compiler + Reanimated 4
4.6M/wk · ships in 12/34
react-native-worklets 8.0
the worklets runtime under Reanimated 4 (now its own package); Shareable values across isolated runtimes
4.7M/wk · ships in 8/34
react-native-skia (2.x)
GPU 2D drawing; v2.1 plays Lottie via Skottie; pairs with Reanimated
1.2M/wk · ships in 3/34
lottie-react-native
designer Lottie/JSON animations; v7 adds visionOS
1.4M/wk · ships in 7/34
Rive — @rive-app/react-native (Nitro) / rive-react-native (legacy)
designer-driven INTERACTIVE vector animation (state machines) — the Lottie alternative; the SDK was rewritten on Nitro under Rive's official scope (@rive-app/react-native, 0.4.x EARLY line): files/view-models become shared typed HybridObjects — Margelo-measured up to 94× multi-view loads + ~4.7× lower memory vs legacy (rewrite authors' own benchmark); legacy unscoped pkg at 9.8.3, quiet since 2026-04
built-in; RN 0.85 shared backend allows layout-prop animation with the native driver (from 0.85.1)
5.6M/wk · ships in 12/34
Moti / LayoutAnimation
declarative transitions; Moti wraps Reanimated — but last published 2025-01 (verified vs npm 2026-07): drifting toward maintenance; fine if installed, prefer plain Reanimated/LayoutAnimation for new work
528k/wk · ships in 2/34
react-native-screen-transitions
custom screen/shared-element transitions FOR React Navigation (blank-stack navigator, bounds-driven navigation.zoom(), gesture choreography); featured on the official React Navigation blog; v3.8 active 2026-07, newer
245k/wk
react-native-ease
animations driven entirely by Core Animation/ObjectAnimator — no per-frame JS OR UI-thread worklet work; author-run benchmark shows it holding frame budget at view counts where Reanimated saturates; young, and see the benchmark-bias caveat in reading
20k/wk
Motion / framer-motion (WEB)
the web (React DOM) animation default — declarative layout/exit/gesture animation; Motion is framer-motion's successor; React Native uses Reanimated instead
RN 0.85 (2026-04) introduced a shared C++ animation backend so Animated and Reanimated ride one engine (built with Software Mansion). Heavy-animation perf routes to react-native-best-practices. RIVE (added 2026-07-13, Margelo blog pass): the RN SDK's Nitro rewrite ships as NEW scoped @rive-app/react-native (0.4.14) while legacy rive-react-native sits at 9.8.3 (both verified vs npm 2026-07-13) — a supersession in progress; WATCH for the new line reaching 1.0 or a formal legacy deprecation before adding a migrate rule. WEB: Motion (the framer-motion successor) is the web animation default — added 2026-06-25 after the evidence-loop corpus self-audit flagged that this [react]-platform entry had options/recommend for React Native only, no web pick (caught from ledgerhr's framer-motion usage). Verified vs the official RN 0.85 blog.
Canonical reading
Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.
First-principles explainer on the real distinction (main-thread contention, compositor-friendly properties, WAAPI) rather than the CSS-is-always-faster myth. A durable animation mental model that applies to web and RN reasoning alike.
Deep dive on driving animations entirely via Core Animation / ObjectAnimator with no per-frame JS, incl. iOS model vs presentation layers and cross-platform spring physics. The mental model for truly native-driven RN animation.
A low-end-Android profiling deep-dive: smoothness is frame-cadence timing, not curve math; the dominant fix is SurfaceView over TextureView (no per-frame texture upload, ~50-65% less RenderThread CPU), plus stable-reference buffer mutation and quantizing per-frame values. With profiler-triangulation methodology (gfxinfo/Perfetto/Hermes).
The only cross-library per-frame benchmark: UI-thread cost of core Animated vs Reanimated (shared values AND the CSS API) vs Ease on real devices — at ~500 animating views only the fully native-driven approach stays under frame budget (Reanimated SVs measured ~36ms/frame). CAVEAT: the author created Ease, the approach that wins — treat the numbers as vendor-run and re-measure on your own screens; the methodology and the per-frame cost model are the durable part.
Uses Suspense to freeze exiting content during animations; explains Fragment refs, useInsertionEffect, and Suspense DOM-update behavior. A durable web exit-animation technique grounded in React internals.
Why the Rive RN SDK's wins came from MODELING, not micro-optimization: the legacy module flattened files/view-models into a per-view God object, so every view re-parsed state; Nitro HybridObjects make them shared typed objects (parse once, render many) — 94× on a 24-view load, ~4.7× lower memory, ~0.3-0.4µs calls vs ~1.5µs TurboModule / ~21µs legacy bridge (iPhone 13 mini, release; the rewrite authors' own benchmark). A general lesson for native-module design: model objects, not modules.
Depth (in-domain rules) is owned by the react-native-best-practices skill — this entry is selection breadth.
The full explanation
The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.
About animation & gestures — where the per-frame work runs
Diataxis: Explanation. This page builds understanding of the animation landscape — the
reasoning behind the picks. It is not an API guide. Animation performance rules (thresholds,
profiling) are owned by react-native-best-practices; GPU drawing by RB-E-GAMES/RB-E-SVG.
Read this for the why.
The one question that organises everything: which thread pays, every frame?
An animation is a piece of work that must complete every ~16ms, forever, while the rest of
your app keeps running. So the durable selection axis is not API style — it is where that
per-frame work executes. There are four tiers, each cheaper than the one before:
JS thread (core Animated with useNativeDriver: false) — every frame crosses into your
busiest thread. One GC pause, one heavy render, and the animation stutters.
UI thread via worklets (Reanimated) — JS code compiled to run on the UI thread's own
runtime (react-native-worklets, now a standalone package). Immune to JS-thread jank, but the
worklet itself still costs UI-thread time per frame.
Fully native drivers (native-driven Animated, react-native-ease) — the animation is
handed to Core Animation / ObjectAnimator once and no per-frame JS or worklet runs at all.
GPU canvas (Skia) — for drawing that isn't view-property animation at all.
Everything in the entry falls out of this ladder, including the failure modes.
The default, and why
React Native → Reanimated 4 + Gesture Handler 3 for real UI-thread animation and gestures.
Web (React DOM) → Motion (framer-motion's successor).
Reanimated 4 sits at tier 2 and is the ecosystem's center of gravity: CSS-style transitions,
shared values, and — since RN 0.85 — a shared C++ animation backend with core Animated, so
the built-in and the library ride one engine instead of two competing ones. Gesture Handler 3
completes it: gestures are recognized natively and feed worklets directly, and its v3 hook-based
API was rebuilt for the React Compiler era (RB-E-REACT-CORE). On the web the same reasoning
lands on Motion: declarative layout/exit/gesture animation over compositor-friendly properties —
Reanimated and Gesture Handler are React Native-only.
The landscape, tier by tier
Reanimated 4 / react-native-worklets — the tier-2 workhorse. Worklets are now their own
package, which matters beyond animation (VisionCamera frame processors, Expo UI synchronous
state — RB-E-NATIVE-UI).
Gesture Handler 3 — native gesture recognition; the input half of the animation story.
Core Animated — fine at tier 3 (native driver) for simple cases; since 0.85.1 it can even
drive layout props natively. Its trap is tier 1: useNativeDriver: false silently moves the work
to the JS thread (the corpus's source-signal rule flags exactly this).
react-native-ease — the tier-3 specialist: animations driven entirely by Core Animation /
ObjectAnimator, zero per-frame JS or worklet work. The author's cross-library benchmark shows it
holding frame budget at view counts where worklet approaches saturate — read with the stated
caveat that the benchmark's author built the winner; the cost model is the durable part.
react-native-screen-transitions — screen/shared-element choreography for React Navigation
(RB-E-NAV); featured on the official React Navigation blog, new — pin.
Skia / Lottie / morph-view — tier 4 and specials: react-native-skia for custom GPU drawing
(and Lottie via Skottie), lottie-react-native for designer-made animation files,
react-native-morph-view for GPU image-morph transitions (niche).
Moti — declarative sugar over Reanimated; dormant since early 2025. Fine if installed;
prefer plain Reanimated or LayoutAnimation for new work.
Tradeoffs and failure modes to name out loud
useNativeDriver: false — the classic tier-1 trap: JS-thread animation that jitters under
load. Native-drive it or move it to Reanimated.
Hundreds of concurrently animating views — even tier 2 pays per-frame worklet cost per
view; at scale (~hundreds) only tier 3 stays under budget. Benchmark before committing an
animation-heavy screen design.
Reaching for Skia to animate view properties — GPU canvas is for drawing; transform/
opacity animation belongs in tiers 2–3.
Two animation systems fighting — pre-0.85 this was real (Animated vs Reanimated timing);
the shared C++ backend resolved it. On ≥0.85 mixing them is no longer an architectural smell.
Web habits on native (and vice versa) — Motion doesn't exist on RN; Reanimated doesn't
exist on the web. Shared-codebase teams keep animation platform-local (RB-E-CROSSPLATFORM).
How it interacts with the rest of the stack
Navigation (RB-E-NAV). Screen transitions are animations with navigation semantics —
react-native-screen-transitions builds them on React Navigation rather than forking it.
Native (RB-E-NATIVE). Worklets are the same machinery VisionCamera v5 frame processors
use; understanding tier 2 here pays off there.
Lists (RB-E-LISTS). List re-renders and animations compete for the same frame budget —
the "render once" discipline in the STATE/LISTS readings is the other half of smoothness.
React core (RB-E-REACT-CORE). Gesture Handler 3's hook API assumes the Compiler era;
animation values deliberately live outside React state to avoid re-render coupling.
In one paragraph
Pick animation tooling by which thread pays every frame. React Native's default is
Reanimated 4 + Gesture Handler 3 — UI-thread worklets, one shared C++ engine with core
Animated since RN 0.85 — with core Animated (native-driven) for trivial cases, ease when
hundreds of concurrent animations demand zero per-frame work, Skia for GPU drawing, and
react-native-screen-transitions for shared-element navigation choreography. On the web, use
Motion. The failure modes are all the same mistake in different clothes: putting per-frame
work on a thread that has better things to do.