Documentation Index
Fetch the complete documentation index at: https://mintlify.com/facebook/react-native/llms.txt
Use this file to discover all available pages before exploring further.
useAnimatedValue is a React hook that creates a persistent Animated.Value instance. The animated value is created only once and persists across component re-renders, making it ideal for animations in functional components.
Signature
function useAnimatedValue(
initialValue: number,
config?: AnimatedConfig
): Animated.Value
Parameters
initialValue - The initial numeric value for the animated value
config (optional) - Configuration options for the animated value
useNativeDriver?: boolean - Whether to use the native driver for animations
Returns
An Animated.Value instance that persists across re-renders.
Usage
import { useAnimatedValue } from 'react-native';
import { View, Animated, Button } from 'react-native';
function FadeInView() {
const opacity = useAnimatedValue(0);
const fadeIn = () => {
Animated.timing(opacity, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}).start();
};
return (
<View>
<Animated.View style={{ opacity }}>
<Text>Fading in!</Text>
</Animated.View>
<Button title="Fade In" onPress={fadeIn} />
</View>
);
}
Common Patterns
Fade Animation
import { useAnimatedValue } from 'react-native';
import { useEffect } from 'react';
import { Animated, View, Text } from 'react-native';
function AutoFadeIn({ children }: { children: React.ReactNode }) {
const opacity = useAnimatedValue(0);
useEffect(() => {
Animated.timing(opacity, {
toValue: 1,
duration: 300,
useNativeDriver: true,
}).start();
}, []);
return (
<Animated.View style={{ opacity }}>
{children}
</Animated.View>
);
}
Scale Animation
import { useAnimatedValue } from 'react-native';
import { Pressable, Animated } from 'react-native';
function ScaleButton({ onPress, children }: { onPress: () => void; children: React.ReactNode }) {
const scale = useAnimatedValue(1);
const handlePressIn = () => {
Animated.spring(scale, {
toValue: 0.95,
useNativeDriver: true,
}).start();
};
const handlePressOut = () => {
Animated.spring(scale, {
toValue: 1,
friction: 3,
tension: 40,
useNativeDriver: true,
}).start();
};
return (
<Pressable onPressIn={handlePressIn} onPressOut={handlePressOut} onPress={onPress}>
<Animated.View style={{ transform: [{ scale }] }}>
{children}
</Animated.View>
</Pressable>
);
}
Slide Animation
import { useAnimatedValue } from 'react-native';
import { useEffect } from 'react';
import { Animated, Dimensions } from 'react-native';
function SlideInView({ children }: { children: React.ReactNode }) {
const slideAnim = useAnimatedValue(-Dimensions.get('window').width);
useEffect(() => {
Animated.spring(slideAnim, {
toValue: 0,
bounciness: 8,
useNativeDriver: true,
}).start();
}, []);
return (
<Animated.View
style={{
transform: [{ translateX: slideAnim }],
}}
>
{children}
</Animated.View>
);
}
Progress Bar
import { useAnimatedValue } from 'react-native';
import { useEffect } from 'react';
import { Animated, View, StyleSheet } from 'react-native';
function ProgressBar({ progress }: { progress: number }) {
const animatedProgress = useAnimatedValue(0);
useEffect(() => {
Animated.timing(animatedProgress, {
toValue: progress,
duration: 500,
useNativeDriver: false, // width animations don't support native driver
}).start();
}, [progress]);
const width = animatedProgress.interpolate({
inputRange: [0, 100],
outputRange: ['0%', '100%'],
});
return (
<View style={styles.progressBarContainer}>
<Animated.View style={[styles.progressBar, { width }]} />
</View>
);
}
const styles = StyleSheet.create({
progressBarContainer: {
height: 8,
backgroundColor: '#e0e0e0',
borderRadius: 4,
overflow: 'hidden',
},
progressBar: {
height: '100%',
backgroundColor: '#4caf50',
},
});
Rotate Animation
import { useAnimatedValue } from 'react-native';
import { useEffect } from 'react';
import { Animated, Easing } from 'react-native';
function SpinningLoader() {
const rotation = useAnimatedValue(0);
useEffect(() => {
Animated.loop(
Animated.timing(rotation, {
toValue: 1,
duration: 1000,
easing: Easing.linear,
useNativeDriver: true,
})
).start();
}, []);
const rotate = rotation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
return (
<Animated.View
style={{
width: 50,
height: 50,
transform: [{ rotate }],
}}
>
{/* Loader icon */}
</Animated.View>
);
}
Color Animation
import { useAnimatedValue } from 'react-native';
import { Pressable, Animated } from 'react-native';
function AnimatedButton({ children }: { children: React.ReactNode }) {
const colorAnim = useAnimatedValue(0);
const handlePressIn = () => {
Animated.timing(colorAnim, {
toValue: 1,
duration: 200,
useNativeDriver: false,
}).start();
};
const handlePressOut = () => {
Animated.timing(colorAnim, {
toValue: 0,
duration: 200,
useNativeDriver: false,
}).start();
};
const backgroundColor = colorAnim.interpolate({
inputRange: [0, 1],
outputRange: ['#2196f3', '#1976d2'],
});
return (
<Pressable onPressIn={handlePressIn} onPressOut={handlePressOut}>
<Animated.View
style={{
backgroundColor,
padding: 16,
borderRadius: 8,
}}
>
{children}
</Animated.View>
</Pressable>
);
}
When to Use
Use useAnimatedValue when you need:
- A single numeric animated value in a functional component
- To animate properties like opacity, scale, rotation, or position
- A persistent animation value that survives re-renders
Alternatives
- useAnimatedValueXY - For animating 2D positions (x, y coordinates)
- new Animated.Value() - Class component equivalent (requires manual ref management in functional components)
- Reanimated library - For more complex animations with better performance
Implementation Details
This hook:
- Uses
useRef to store the Animated.Value instance
- Creates the animated value only once on first render
- Returns the same instance on subsequent re-renders
- The initial value is only used during the first render
// Simplified implementation
function useAnimatedValue(initialValue: number, config?: AnimatedConfig) {
const ref = useRef<Animated.Value | null>(null);
if (ref.current == null) {
ref.current = new Animated.Value(initialValue, config);
}
return ref.current;
}
- Always use
useNativeDriver: true when possible for better performance
- Native driver supports:
transform and opacity
- Native driver does NOT support:
layout properties (width, height, etc.) and backgroundColor
- Animations run on the native thread, avoiding JavaScript thread blocking
See Also