Animated API is a built-in declarative animation library in React Native that provides 60 FPS animation without burdening the JavaScript thread. According to the official React Native 0.76 (2025) documentation, Animated API supports useNativeDriver for all animation types, moving computations to the native thread via UI Manager. The library allows creating complex animation chains, interactive gestures, and interpolation of any style properties — from opacity to transformation.
Key Takeaways
Animated API is a declarative animation library built into the core of React Native, designed for creating smooth, performant animations in mobile applications. Unlike CSS animations in web development, Animated API works directly with the native UI thread via the JavaScript bridge or native driver. The library is built around the concept of Animated.Value — a container that stores a numeric value and automatically subscribes all dependent components to changes. When the value changes via Animated.timing or Animated.spring, the library calculates intermediate states without re-rendering React components, which is critical for maintaining 60 FPS. Animated API supports all style properties, including transform, opacity, width, height, top, left, and backgroundColor. React Native documentation recommends Animated API for all animation scenarios requiring high performance and predictable behavior on both platforms.
The foundation of Animated API is Animated.Value, a numeric value container initialized via the constructor new Animated.Value(0). Each Animated.Value stores an initial number and provides animate methods: timing, spring, and decay. The timing method creates linear or easing animation with duration, delay, and easing parameters. The spring method implements physical spring animation with friction, tension, and velocity parameters. The decay method creates animation with inertia and damping — useful for swipes and scrolling. All methods return an Animated.Composite object that can be started via start() and stopped via stop(). Animation runs in a separate thread: when useNativeDriver = true, calculations happen in the native UI thread, leaving the JavaScript thread free for event handling and logic.
Animated.timing is the basic animation method with controlled duration. It accepts configuration: toValue, duration (default 500ms), easing (Easing.linear by default), and delay. Easing functions from the Easing module allow non-linear acceleration: Easing.bezier, Easing.elastic, Easing.bounce. For uniform speed animation use Easing.linear, for natural acceleration use Easing.inOut. Important: Animated.timing guarantees the animation will finish exactly at toValue within the specified time, regardless of device load.
Animated.spring implements a spring animation model based on Hooke’s law. The friction parameter controls oscillation count: the higher the friction, the faster the stop. The tension parameter determines spring stiffness: high tension speeds up movement. The velocity parameter sets the initial speed for animation with inertia — critically important for animations following user gestures. Animated.spring has no fixed duration — animation completes when speed and amplitude reach threshold values.
Animated API provides four built-in animated components: Animated.View, Animated.Text, Animated.ScrollView, and Animated.Image. Each is a wrapper over the corresponding native component that supports passing Animated.Value to style properties. Animated.View is the most used component, accepting the same props as a regular View, but with support for animated values in style. Animated.Text is useful for animating text color or inter-letter spacing. Animated.ScrollView allows animating scrollTo and contentOffset. Animated.Image supports animated opacity and scale during image loading. If you need to animate another component, use Animated.createAnimatedComponent(MyComponent).
import React from 'react';
import { Animated, View, Button } from 'react-native';
const FadeInView = () => {
const opacity = useRef(new Animated.Value(0)).current;
const fadeIn = () => {
Animated.timing(opacity, {
toValue: 1,
duration: 1000,
useNativeDriver: true,
}).start();
};
return (
View
Animated.View { style: [{ opacity }] }
Button title="Fade In" onPress={fadeIn}
);
};
Interpolation is a mechanism for converting an input numeric range of Animated.Value into output values of another type. The interpolate method accepts configuration with inputRange (array of input values) and outputRange (array of output values). OutputRange types: numbers (coordinates, opacity), strings (rotation angles with ‘deg’), hex colors (‘#ff0000’), transform objects. Interpolation supports easing and extrapolate — behavior outside the specified range (clamp, extend, identity). For example, during a drag gesture, you can map finger position from 0 to 200 into opacity from 1 to 0, creating a fade effect on swipe. The interpolation system allows creating complex multi-step animations: value 0-0.5-1.0 can map to yellow-orange-red.
const spinValue = new Animated.Value(0);
Animated.timing(spinValue, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true,
}).start();
const spin = spinValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
Animated API supports three animation composition modes: Animated.sequence, Animated.parallel, and Animated.stagger. Animated.sequence runs animations one after another: each next starts after the previous completes. Animated.parallel runs all animations simultaneously with one shared completion callback. Animated.stagger runs animations with a delay between each start — useful for creating wave effects. Compositions can be nested: sequence of parallel groups or parallel of sequences. This allows creating complex chains: staggered element appearance animation, parallel slide-in with fade-in, then a sequence of bounce and shake.
Animated.sequence([
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}),
Animated.parallel([
Animated.timing(scaleAnim, {
toValue: 1.1,
duration: 200,
useNativeDriver: true,
}),
Animated.spring(colorAnim, {
toValue: 1,
friction: 4,
useNativeDriver: true,
}),
]),
]).start();
useNativeDriver is an animation configuration option that moves all animation logic from the JavaScript thread to the native UI thread. Without useNativeDriver, animations execute via the JavaScript bridge: each value change is sent to the native thread, causing delays when the JS thread is busy with async operations. With useNativeDriver = true, Animated.Value updates directly on the native side, leaving the JavaScript thread free for event handling, API requests, and React reconciliation. Limitation: useNativeDriver only supports non-layout properties — opacity, transform, backgroundColor (via PlatformColor). For layout properties (width, height, top, left), NativeAnimatedModule or LayoutAnimation is required. According to React Native 0.76, all animated properties are supported via native driver except layout-based ones. useNativeDriver mode is recommended for all animations where possible — it boosts FPS from 30-40 to a stable 60.
PanResponder is a built-in React Native gesture handling system that integrates well with Animated API. PanResponder provides onPanResponderMove and onPanResponderRelease callbacks where Animated.Value can be updated based on finger position. For more complex gestures — swipe, pinch, rotation — use the react-native-gesture-handler library, which works synchronously with animations and provides 60 FPS even with multi-finger gestures. Gesture Handler provides Animated.event — a method that directly binds a gesture to Animated.Value without manual callback handling. The combination of Gesture Handler + Animated API is the industry standard for interactive animations in React Native applications.
Animated.event is a method that binds a native event (e.g., gestureEvent) directly to Animated.Value. Unlike manual callback handling, Animated.event works synchronously in the native thread and does not require the JavaScript bridge for each frame. This provides smooth animation even during fast swipes. Animated.event accepts an array of mappings, where each element binds an event field to Animated.Value. Nested access is supported: Animated.event([{ nativeEvent: { translationX: xValue } }]).
Let’s look at three practical examples of using Animated API in React Native projects. The first example is a card appearance animation with opacity + translateY sequence. The second example is a button pulse animation using spring. The third example is an interactive drag element with PanResponder. All examples use useNativeDriver = true and follow React Native 0.76 best practices.
const CardWithAnimation = () => {
const anim = useRef(new Animated.Value(0)).current;
React.useEffect(() => {
Animated.spring(anim, {
toValue: 1,
friction: 6,
tension: 40,
useNativeDriver: true,
}).start();
}, []);
const translateY = anim.interpolate({
inputRange: [0, 1],
outputRange: [50, 0],
});
return (
Animated.View {
style: [{ opacity: anim, transform: [{ translateY }] }]
}
);
};
Spring animation creates a natural pulse effect using a physical spring model. Low friction (2-4) and high tension (100-150) settings produce soft oscillations that decay naturally. Use Animated.loop for infinite pulsing with a sequence cycle: scale → 1.2, scale → 1.0. Pulsing is used for loading indicators, notifications, and accent buttons.
Frequently Asked Questions
Animated API provides full control over animation — duration, easing, interpolation, composition. LayoutAnimation is a built-in React Native system for animating layout changes with automatic interpolation. Animated API requires explicit declaration of Animated.Value and configuration, but allows creating complex chains. LayoutAnimation fires automatically on state changes and is simpler to use, but limited in flexibility.
Yes, width and height can be animated via Animated API, but they do not support useNativeDriver. Layout property animation requires the JavaScript driver, as the native driver only works with non-layout properties. Use Animated.Value with toValue for width/height and set useNativeDriver to false. For better layout animation performance, consider LayoutAnimation or react-native-reanimated.
Call the stop() method on the animation object returned by Animated.timing or Animated.spring. Example: animRef.stop(). If the animation is part of a sequence or parallel, stop() stops the entire group. To check status, use the callback in start(callback) — it receives a result object with finished: false on forced stop.
Animated.ValueXY is a container for two-dimensional coordinates, storing two Animated.Value: x and y. Use it for animating element position on screen — drag, pan, swipe. ValueXY provides ready-made getLayout() for styles and getTranslateTransform() for transformations. This is convenient when working with PanResponder where both axes need to be animated simultaneously.
Use the React Native Performance Monitor, built into the dev menu (Cmd+D / Cmd+M). Enable FPS Monitor — it shows UI FPS and JS FPS in real time. For programmatic measurement, use import { InteractionManager } to track animation completion. Stable 60 UI FPS and 50+ JS FPS indicate a well-optimized animation. If UI FPS drops below 30, disable useNativeDriver or optimize the number of concurrent animations.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also