In React Native, the Animated API is used because it gives you a performant and flexible way to create animations in your app.
🔑 Reasons to Use the Animated API
-
Performance
If you animate with setState, every frame causes a full React render, which is slow.The Animated API runs animations on the native UI thread (especially with useNativeDriver: true), so animations stay smooth (60fps)(frames per second) even if JavaScript is busy. -
Declarative Animations
You describe what should happen (e.g., “move this box from X=0 to X=200 over 500ms”), and React Native handles the how. Makes animations easier to reason about. -
Reusability
The same Animated.Value can drive multiple properties (opacity, scale, rotation, etc.). Easier than manually tracking multiple states. -
Gestures + Physics
Supports spring animations, decay (momentum), and interactions with touch gestures. Perfect for natural-feeling UI like swipes, drags, and bounces. -
Cross-Platform Consistency
Works on both iOS and Android with the same API, without you needing to use native code for animations. -
Interpolation
You can map one animated value into different ranges. Example:
const progress = useRef(new Animated.Value(0)).current;
// Slide horizontally
const translateX = progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 200],
});
// Fade out
const opacity = progress.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [1, 0.5, 0], // custom curve
});
// Rotate
const rotate = progress.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "360deg"],
});
All are derived from the same progress value.
→ This allows chaining multiple visual effects from one value.
🔹 Step by step (useRef(new Animated.Value(0)).current;)
1- new Animated.Value(0)
Creates an Animated.Value object starting at 0.
This is the special type React Native uses to drive animations (instead of a normal number).
2- useRef(…)
Ensures the value is persistent across re-renders.
Without useRef, every re-render would create a new Animated.Value, resetting the animation back to 0.
With useRef, React will keep the same object during the component’s lifecycle.
3- .current
useRef returns an object like { current: }.
.current gives you the actual Animated.Value stored inside.
Example
import React, { useRef, useEffect } from "react";
import { Animated, View } from "react-native";
export default function Box() {
const fadeAnim = useRef(new Animated.Value(0)).current; // start opacity at 0
useEffect(() => {
Animated.timing(fadeAnim, {
toValue: 1,
duration: 2000,
useNativeDriver: true, // run on UI thread
}).start();
}, []);
return (
);
}
👉 Without Animated, you’d have to manually update opacity on every frame — very inefficient.
✅ In short:
We need the Animated API in React Native because it makes animations smooth, efficient, declarative, and easy to combine with gestures and physics.
🔹 What happens with setState?
- When you call setState, React re-renders in the JS thread.
- That means every frame of the animation depends on the JS thread being free and fast.
- If the JS thread is busy (fetching API, parsing JSON, rendering a heavy component), the animation drops frames → stutters.
- That’s why animations with setState often run at 30fps or less, instead of smooth 60fps.
⚖️ Quick Comparison between Animated(built-in) and react-native-reanimated
- Performance –> Good, but JS can block –> Excellent (runs on UI thread)
- Complexity handling –> Basic animations only –> Handles very complex flows
- Gesture support –> Limited –> designed to work seamlessly with react-native-gesture-handler.
- Ease of use –> Simple API –> Steeper learning curve
- Dependencies –> Built-in (no install) –> Requires installation & setup
- Recommended for production –> Small/simple apps –> Medium/large apps with rich UI