◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Dev Tools
⬡ Dev Tools/2026-03-30Advanced

Rork × React Native Reanimated & Gesture Handler — Building 60fps Animations and Advanced Gesture Interactions

Keeping Reanimated 3 and Gesture Handler at 60fps, told through the production pitfalls I hit running wallpaper and calming-tone apps: delayed runOnJS, useDerivedValue caching, FlashList pairing, and missing cancelAnimation — each with real measurements.

Reanimated10Gesture HandlerAnimation8Performance25UI/UX3React Native239Rork585

✦ Premium Article

Setup and context — Why Reanimated and Gesture Handler Matter

One of the defining factors of a high-quality mobile app is the smoothness of its animations and the responsiveness of its gesture handling. Users perform scrolls, swipes, and pinch-to-zoom gestures instinctively — even the slightest stutter or delay creates a perception that the app is poorly built.

React Native's built-in Animated API handles basic animations well enough, but it falls short when you need complex gesture-driven animations or consistent 60fps transitions. This is where React Native Reanimated 3 and React Native Gesture Handler come in.

Reanimated runs animation logic directly on the UI thread (native side), completely bypassing JavaScript thread bottlenecks. Gesture Handler recognizes gestures at the native level, and when combined with Reanimated, delivers the kind of "sticks to your finger" responsiveness that users expect from premium apps.

I'm Masaki Hirokawa, an indie developer who has been running iOS and Android apps on my own since 2013 — mostly quiet utilities in the wallpaper, calming-tone, and intention categories, around 50 million cumulative downloads, that people open a little bit every day. (I also run the Dolice Labs sites.) Apps like these don't need flashy effects, but a single hitch in a swipe or pinch translates directly into churn. After shipping Reanimated and Gesture Handler into real products, I kept running into cases that follow the docs perfectly yet break only in production. This guide covers the core architecture and four implementation patterns, and then the "things the docs won't tell you" — each backed by real numbers.


Reanimated 3 Architecture — Understanding Worklets and Shared Values

Why the Standard Animated API Isn't Enough

React Native's standard Animated API computes animation values on the JS thread and sends them to the UI thread via the bridge. Under this architecture, when the JS thread is busy with heavy operations (API calls, data transformations, etc.), animations stutter.

Reanimated 3 solves this with Worklets — JavaScript functions that execute directly on the UI thread. Simply adding the 'worklet' directive at the top of a function causes it to be serialized and run on the UI thread automatically.

Shared Values — Fast Cross-Thread Data Sharing

Values created with useSharedValue can be safely accessed from both the JS and UI threads. Because they bypass the traditional bridge, value updates are reflected without frame drops.

import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  withTiming,
  Easing,
} from 'react-native-reanimated';
 
// Inside a component
// Create a Shared Value (accessible from both UI and JS threads)
const translateX = useSharedValue(0);
const scale = useSharedValue(1);
 
// Declaratively define animated styles
// This function runs on the UI thread, avoiding JS thread blocking
const animatedStyle = useAnimatedStyle(() => ({
  transform: [
    { translateX: translateX.value },
    { scale: scale.value },
  ],
}));
 
// Update values with spring animation
// damping: oscillation decay rate, stiffness: spring tension
const handlePress = () => {
  translateX.value = withSpring(200, {
    damping: 15,      // Lower = more bounce
    stiffness: 150,   // Higher = faster motion
    mass: 1,          // Mass (affects inertia)
  });
  scale.value = withTiming(1.2, {
    duration: 300,
    easing: Easing.bezier(0.25, 0.1, 0.25, 1),
  });
};
 
// Usage in JSX
// <Animated.View style={[styles.box, animatedStyle]} />

Derived Values — Computed Animation Values

useDerivedValue lets you create computed values that automatically update on the UI thread based on other Shared Values.

import { useDerivedValue, interpolate } from 'react-native-reanimated';
 
// Auto-compute rotation based on translateX
const rotation = useDerivedValue(() => {
  // Map translateX range -200..200 to rotation -30..30 degrees
  return interpolate(
    translateX.value,
    [-200, 0, 200],
    [-30, 0, 30],
    'clamp' // Clamp values outside range
  );
});
 
// Opacity also changes in sync
const opacity = useDerivedValue(() => {
  return interpolate(
    Math.abs(translateX.value),
    [0, 150, 200],
    [1, 0.8, 0.3]
  );
});

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦The FlashList + single Shared Value pattern that cut a wallpaper grid's initial render from 820ms to 310ms and memory from 180MB to 96MB
✦Six production pitfalls found through Crashlytics and on-device profiling: delayed runOnJS, useDerivedValue caching, missing cancelAnimation, and more
✦The two withSpring presets I settled on across 50M cumulative downloads, plus an on-device checklist for ScrollView vs. gesture conflicts
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ Dev Tools2026-04-25
Skeleton Screens in Rork Apps — Practical Patterns for Better Perceived Performance
If your Rork app still shows a spinner on a blank screen during load, you are leaving a lot of perceived performance on the table. Here is how I drop skeleton screens and shimmer effects into Rork-generated React Native code without over-engineering it.
⬡ Dev Tools2026-07-24
Collapsing Duplicate Requests Into One: A Reference-Counted Single-Flight Layer
When several components fire the same API call at launch, you get a burst of identical requests. Here is a single-flight layer that shares one in-flight promise instead: how to build the key that decides the folding, the trap of handing out a failed promise forever, the trap of one caller's abort cancelling everyone, and the test that keeps it all from regressing, with the real network numbers alongside.
⬡ Dev Tools2026-05-02
When Your FlatList Starts Stuttering: Migrating Rork Apps to FlashList v2
When your Rork app's long lists start feeling sluggish, migrating to FlashList v2 makes scrolling dramatically smoother. Here is the practical migration path, taking advantage of v2's removal of estimatedItemSize.