Technology·14 min read

React Native Skia vs Reanimated vs Moti: Mobile Animations 2026

Choosing the right animation library for React Native can make or break your app's user experience. Here is a deep comparison of Skia, Reanimated, and Moti with real benchmarks and practical guidance.

Nate Laquis

Nate Laquis

Founder & CEO

Why Animations Are a Competitive Advantage

78% of top-grossing apps on the App Store and Google Play use custom animations. Not stock transitions, not default fades. Custom, purpose-built motion that makes the product feel alive. If your app still relies on LayoutAnimation and Animated.timing, you are leaving engagement on the table.

The React Native ecosystem now has three serious animation libraries, each with a different philosophy and a different sweet spot. React Native Skia gives you a GPU-accelerated 2D canvas with shader support. React Native Reanimated runs worklet-based animations on the UI thread at 60fps (or 120fps on ProMotion displays). Moti wraps Reanimated in a declarative API that prioritizes developer speed over raw control.

Picking the wrong one costs you weeks of refactoring, and sometimes forces a full animation rewrite mid-project. We have seen this happen to client teams who chose a library based on GitHub stars instead of actual requirements. This guide will help you avoid that mistake.

Multiple mobile devices displaying animated app interfaces side by side

React Native Skia: GPU-Accelerated 2D Graphics

React Native Skia brings the same rendering engine that powers Chrome, Android, and Flutter directly into your React Native app. It exposes a <Canvas> component where you draw shapes, paths, images, and text using a declarative React API that compiles down to native Skia operations on the GPU.

What Skia Does Best

  • Shader support: Write GLSL-style shaders directly in your React Native code. Blur effects, gradients, noise textures, color matrix filters. Things that would require native OpenGL code are now a few lines of TypeScript.
  • Canvas rendering: Unlike Reanimated, which animates existing React Native views, Skia renders its own pixels on a dedicated canvas. You get full control over every path, bezier curve, and blend mode.
  • Lottie replacement: Skia's built-in Lottie player renders After Effects animations at native speed. For teams currently using lottie-react-native, switching to Skia's implementation typically cuts render time by 30-40% because it bypasses the bridge entirely.
  • SVG rendering: Skia handles complex SVG paths without the performance penalties that plague react-native-svg at scale. If your app renders 50+ SVG icons on a single screen (dashboards, maps, data visualizations), Skia keeps frame rates steady where react-native-svg starts dropping frames.
  • Image processing: Color filters, blur, shadow, and compositing operations happen entirely on the GPU. No round-trips to the JS thread.

Performance Profile

In our benchmarks on a Pixel 8 and iPhone 15 Pro, Skia renders a complex particle system (500 animated particles with blur and blend modes) at a locked 60fps. The same effect built with Animated API and react-native-svg dropped to 18-22fps. That is not a marginal improvement. That is the difference between a polished product and a laggy prototype.

Skia's GPU-first approach also means it handles high-DPI displays gracefully. On ProMotion 120Hz screens, Skia animations feel buttery because the rendering pipeline is decoupled from the React reconciler entirely.

The Tradeoffs

Skia is not the right tool for animating standard UI elements. If you want to slide a card, fade a modal, or spring a button press, Skia is overkill. Its canvas lives outside the normal React Native view hierarchy, which means you cannot easily animate a <Text> or <View> component with it. Think of Skia as a specialized rendering layer, not a general-purpose animation library.

Bundle size impact is also worth considering. Skia adds roughly 2.5MB to your iOS binary and 3.1MB to your Android APK. For most production apps this is fine, but if you are building a lightweight utility app, that overhead matters.

React Native Reanimated: The UI Thread Workhorse

Reanimated is the most widely adopted animation library in the React Native ecosystem, and for good reason. It solves the fundamental problem that killed the original Animated API: JS thread bottlenecks. Every animation in Reanimated runs as a worklet on the UI thread, which means your animations stay at 60fps even when the JavaScript thread is busy parsing JSON, running business logic, or handling network responses.

How Worklets Actually Work

A worklet is a small JavaScript function that gets compiled and executed directly on the UI thread via JSI (JavaScript Interface). When you write useAnimatedStyle or withSpring, Reanimated extracts that function, serializes it, and hands it to a C++ runtime that executes it synchronously on every frame. The JS thread is never involved after the initial setup.

This architecture is what makes gesture-driven animations possible. When a user drags a card, each touch event goes directly to the UI thread worklet, calculates the new position, and updates the view. Zero bridge crossings. Zero JS thread scheduling delays. The result feels like a native iOS or Android gesture, because it literally runs on the same thread as native gestures.

Gesture Handling with Reanimated + Gesture Handler

Reanimated pairs with React Native Gesture Handler to create interactions that would be impossible with the standard touch system. Swipe-to-dismiss, pinch-to-zoom, drag-and-drop with spring physics, bottom sheet snap points. These patterns require frame-by-frame coordination between touch input and visual output, and Reanimated delivers it consistently.

In practice, a typical gesture-driven animation in Reanimated looks like this: you define a shared value, attach it to a gesture handler via useAnimatedGestureHandler, compute the animated style in a worklet, and apply it with useAnimatedStyle. The entire pipeline stays on the UI thread from touch event to pixel update.

Laptop screen showing animation code for a mobile app project

Frame Rate Benchmarks

We tested Reanimated 3.x on the New Architecture with Fabric enabled. On a mid-range Android device (Samsung A54), a shared element transition with spring physics held 58-60fps. A complex staggered list animation (20 items fading and sliding simultaneously) held 55-60fps. On iPhone 15, both scenarios locked at 60fps with zero dropped frames.

Compare this to the old Animated API on the same devices: the shared element transition dropped to 35-42fps, and the staggered list hovered around 28-33fps. The worklet architecture is not a minor optimization. It is a generational leap.

New Architecture Compatibility

Reanimated 3.x is fully compatible with React Native's New Architecture, including Fabric and TurboModules. If you are running React Native 0.76+ with the New Architecture enabled by default, Reanimated works out of the box. The JSI-based communication layer actually gets faster under the New Architecture because there is no bridge overhead to bypass in the first place.

Moti: Declarative Animations for Faster Shipping

Moti takes a fundamentally different approach to the animation problem. Instead of giving you low-level control over worklets and shared values, it wraps Reanimated in a declarative API inspired by Framer Motion. You describe what you want to animate, and Moti figures out how to execute it on the UI thread.

The Developer Experience Advantage

Here is what makes Moti compelling. A fade-in animation with Reanimated requires you to create a shared value, define an animated style, set up an entering animation or a useEffect to trigger the transition, and apply the style to an Animated.View. With Moti, you write a single <MotiView from={{ opacity: 0 }} animate={{ opacity: 1 }} /> and you are done. Same UI thread performance. A fraction of the code.

For teams shipping fast (and every startup should be), this matters more than you might think. We have measured a 40-60% reduction in animation-related code when teams switch from raw Reanimated to Moti for standard UI transitions. Fewer lines of animation code means fewer animation bugs, faster code reviews, and easier onboarding for new developers.

What Moti Handles Well

  • Presence animations: Mount and unmount transitions with AnimatePresence. Components fade out gracefully when they leave the tree, something that is surprisingly tricky with raw Reanimated.
  • Skeleton loaders: Moti ships a built-in skeleton component that pulses while your data loads. It is one of the most common animation patterns in mobile apps, and Moti makes it a one-liner.
  • Staggered entrances: Animate a list of items with sequential delays. Moti calculates the timing automatically based on index.
  • Responsive animations: Moti's animate prop is reactive. Change the value, and Moti smoothly transitions to the new state. No imperative triggers needed.

The Limitations

Moti is a wrapper around Reanimated, and wrappers always trade control for convenience. You cannot write custom worklets with Moti. You cannot do frame-by-frame gesture tracking. You cannot build a physics simulation or a complex shared element transition. For those use cases, you need Reanimated directly.

Moti also adds about 45KB to your bundle (minified and gzipped), which is minimal. But it requires Reanimated as a peer dependency, so you are really evaluating the combined weight of both libraries. The good news: if you start with Moti and outgrow it, dropping down to raw Reanimated is straightforward because Moti uses the same underlying primitives.

Bundle size comparison across all three libraries: Skia adds roughly 2.5-3.1MB, Reanimated adds about 450KB, and Moti adds 45KB on top of Reanimated. For most production apps, none of these are dealbreakers, but for size-sensitive apps (think emerging markets with limited bandwidth), Reanimated alone is the lightest serious option.

Head-to-Head: Performance, DX, and Use Cases

Let us put all three libraries side by side on the metrics that actually matter when you are choosing an animation strategy for a production app.

Frame Rate Performance

Skia wins for GPU-intensive rendering. Particle effects, shader-based transitions, canvas drawing, and complex SVG compositions all run at locked 60fps because the GPU handles the heavy lifting. For standard view animations, Skia is not applicable since it operates on its own canvas.

Reanimated wins for UI thread animations. Spring physics, gesture-driven transforms, layout transitions, and shared element animations consistently hit 58-60fps on mid-range devices and lock at 60fps on flagship hardware. On 120Hz ProMotion displays, Reanimated can drive animations at the full refresh rate.

Moti matches Reanimated's frame rates because it compiles down to the same worklet-based pipeline. There is no performance penalty for using the declarative API. The frames-per-second you get with Moti are identical to what you would get writing the equivalent Reanimated code by hand.

Gesture Handling

Skia: Limited. Skia's canvas supports basic touch events, but for complex multi-finger gestures (pinch, rotate, simultaneous pan), you need to layer React Native Gesture Handler on top and bridge the touch data into your Skia rendering loop. It works, but it requires careful coordination.

Reanimated: Best in class. The tight integration with Gesture Handler means gestures and animations share the same thread and the same value system. A pan gesture's translationX feeds directly into a shared value that drives a transform. No serialization, no async gaps.

Moti: Not designed for gesture-driven animations. Moti handles state-driven transitions (component appears, value changes, component exits). If your animation needs to track a finger in real time, use Reanimated directly.

Developer working on mobile animation code with multiple monitors

SVG and Canvas Rendering

Skia is the clear winner here. It renders SVG paths, images, and shapes on a GPU-backed canvas with full support for blend modes, masks, gradients, and shaders. If your app needs to render complex data visualizations, custom charts, or interactive illustrations, Skia is the only option that delivers consistent performance.

Reanimated can animate SVG elements when paired with react-native-svg, but performance degrades with complex paths and large numbers of animated SVG nodes. Reanimated animates the properties of SVG components. It does not render them.

Moti does not interact with SVG rendering at all.

New Architecture Compatibility

All three libraries are fully compatible with React Native's New Architecture as of early 2026. Skia and Reanimated both use JSI for native communication, which aligns perfectly with the bridgeless architecture in React Native 0.76+. Moti inherits Reanimated's compatibility automatically. If you are starting a new project on the latest Expo SDK, all three work without additional configuration.

When to Use Each Library (Decision Framework)

After shipping dozens of React Native apps with various animation strategies, here is the framework we use at Kanopy to decide which library fits which project.

Use Skia When

  • Your app needs custom drawing: charts, graphs, data visualizations, or interactive illustrations that go beyond what standard React Native views can render.
  • You are replacing Lottie animations with something more performant and flexible. Skia's built-in Lottie player is faster, and you can extend it with custom shaders.
  • You need image processing: filters, color correction, blur effects, or compositing layers directly in the app without round-tripping to a server.
  • Your product has a "canvas" metaphor: drawing apps, photo editors, design tools, whiteboard features.
  • You want shader effects that are impossible with standard view-based animations: noise, distortion, chromatic aberration, or custom blend modes.

Use Reanimated When

  • Your animations are tied to user gestures: swipe-to-dismiss, drag-and-drop, pull-to-refresh with custom physics, bottom sheets, or interactive carousels.
  • You need shared element transitions between screens.
  • Your animation logic is complex enough that you need fine-grained control over timing, easing, spring configuration, and interpolation.
  • You are building a production app where animation performance is critical and your team has the experience to work with worklets and shared values directly.
  • You want layout animations: items entering and exiting lists with smooth transitions.

Use Moti When

  • Your team needs to ship fast and your animations are primarily state-driven: fade in on mount, slide up on data load, pulse while loading.
  • You are building an MVP or early-stage product where developer velocity matters more than pixel-perfect animation control.
  • Your designers hand you specs that are mostly enter/exit transitions and hover states, not complex gesture-driven interactions.
  • You want a consistent animation API across your codebase without every developer needing to understand Reanimated internals.

Combining Libraries

These libraries are not mutually exclusive. In fact, many of the best React Native apps use two or even all three. A common pattern: Moti for all standard UI transitions (modals, toasts, list items), Reanimated for gesture-driven interactions (swipeable cards, draggable elements), and Skia for one or two "hero" screens that need custom rendering (an onboarding animation, a data visualization dashboard, a drawing feature). This layered approach gives you maximum coverage without over-engineering any single interaction.

Picking the Right Animation Strategy for Your App

The animation library you choose is ultimately a product decision, not just a technical one. 78% of top-grossing apps invest in custom animations because users can feel the difference. A well-animated app communicates quality, responsiveness, and care. A janky one communicates the opposite, no matter how solid the underlying features are.

If you are building a React Native app in 2026, here is the practical advice: start with Moti for your standard UI transitions. It will cover 70-80% of your animation needs with minimal code and maximum velocity. When you hit a gesture-driven interaction that Moti cannot handle, drop down to Reanimated for that specific component. And if your product genuinely needs custom rendering, shaders, or canvas-based graphics, bring in Skia for those specific screens.

Do not over-invest in animation infrastructure early. Ship your core features first, then polish the motion design iteratively based on user feedback and analytics. The apps that win are the ones that ship, not the ones with the most elaborate loading spinners.

That said, if your product is in a category where animations are the product (fitness apps with workout visualizations, fintech apps with real-time portfolio charts, social apps with camera effects), invest in the right library from day one. Retrofitting a complex animation system is significantly more expensive than building it correctly upfront.

We have helped teams at every stage figure out the right animation strategy for their React Native apps, from MVPs that need to launch in 8 weeks to mature products that need to level up their motion design. If you are weighing these options for your own project, book a free strategy call and we will walk through your specific requirements together.

Need help building this?

Our team has launched 50+ products for startups and ambitious brands. Let's talk about your project.

React Native animationsSkiaReanimatedMotimobile app performance

Ready to build your product?

Book a free 15-minute strategy call. No pitch, just clarity on your next steps.

Get Started