AlgoInsight

Q&A

How to create animations using React Native Reanimated

By AlgoInsight Team2026-06-07frontendoperating-systemsreactjavascript

Overview

Standard React Native's Animated API often runs animation logic on the JavaScript thread, which can stutter under load. Reanimated moves animations to the native UI thread using "worklets" (functions that run natively), delivering 60fps animations decoupled from JS work. The current API is hook-based and declarative.

graph LR
    A[useSharedValue: animated value] --> B[useAnimatedStyle: derive style]
    B --> C[Apply to Animated.View]
    A --> D[Update via withTiming / withSpring]
    D --> E[Runs on UI thread → smooth 60fps]
    style E fill:#1e1b4b,color:#fff

Core Building Blocks

Basic Example: Fade + Move

import Animated, {
  useSharedValue, useAnimatedStyle, withTiming, withSpring,
} from "react-native-reanimated";
import { Button, View } from "react-native";

function Box() {
  const offset = useSharedValue(0);
  const opacity = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: offset.value }],
    opacity: opacity.value,
  }));

  const move = () => {
    offset.value = withSpring(offset.value === 0 ? 150 : 0);  // spring physics
    opacity.value = withTiming(opacity.value === 1 ? 0.3 : 1, { duration: 300 });
  };

  return (
    <View>
      <Animated.View style={[{ width: 80, height: 80, backgroundColor: "#6366f1" }, animatedStyle]} />
      <Button title="Animate" onPress={move} />
    </View>
  );
}

Assigning withSpring(...)/withTiming(...) to a shared value's .value automatically animates it on the UI thread; useAnimatedStyle maps those values to styles.

Animation Helpers

Function Effect
withTiming(to, {duration, easing}) Linear/eased transition over a duration
withSpring(to, {damping, stiffness}) Natural spring physics
withRepeat(anim, count, reverse) Repeat an animation (use -1 for infinite)
withSequence(a, b, c) Run animations one after another
withDelay(ms, anim) Delay before starting
// pulsing loop
scale.value = withRepeat(withTiming(1.2, { duration: 600 }), -1, true);

Gestures and Scroll

Reanimated pairs with react-native-gesture-handler for drag/pan, and offers useAnimatedScrollHandler for scroll-driven animations and useAnimatedGestureHandler/the modern Gesture API for interactive, UI-thread-driven gestures - all without round-tripping to JS each frame.

Worklets (the key concept)

Functions marked as worklets (the body of useAnimatedStyle, or annotated with "worklet") are compiled to run on the UI thread. This is why Reanimated is fast - the animation logic doesn't wait on the JS thread. To call back into JS from a worklet, use runOnJS(...).

Why This Matters in Interviews

React Native interviews use this to test performance awareness. The headline: Reanimated runs animations on the UI thread via worklets, so they don't stutter when JS is busy (the core advantage over the classic Animated API). Know the v2/v3 hook trio (useSharedValue, useAnimatedStyle, withTiming/withSpring), that updating .value drives animation, and runOnJS to bridge back. Mentioning gesture-handler integration for interactive animations shows depth.

Common Pitfalls

References

More answers