Using Reanimated for Advanced Animations
1. Installing Reanimated Library
| Step | Description | Command |
|---|---|---|
| 1 | Install the Reanimated library using npm | npm install react-native-reanimated |
| 2 | Install the Reanimated library using yarn | yarn add react-native-reanimated |
Note: Reanimated requires React Native version 0.62 or higher.
2. Using useSharedValue Hook
The useSharedValue hook is a core building block in Reanimated for managing values that can be shared between the JavaScript and UI threads. It allows you to define values that can be mutated in the UI thread without triggering a re-render of your component.
| Property | Description | Example |
|---|---|---|
| value | The current value of the shared value. | const sharedValue = useSharedValue(0); |
| onChange | Callback function that is called whenever the value changes. | const sharedValue = useSharedValue(0, (newVal) => console.log(newVal)); |
Example: Basic useSharedValue usage
import { useSharedValue } from 'react-native-reanimated';
const MyComponent = () => {
const scale = useSharedValue(1);
const animate = () => {
'worklet';
scale.value = 1.5;
};
return (
<Animated.View
style={[
styles.box,
{
transform: [{ scale: scale.value }],
},
]}
>
<TouchableOpacity onPress={animate}>
<Text>Tap to animate</Text>
</TouchableOpacity>
</Animated.View>
);
};
Note: The
useSharedValue is designed to be used inside the UI thread, and its value can only be updated using worklets. Direct updates from JavaScript will not have any effect.
3. Using useAnimatedStyle Hook
| Property | Description | Usage |
|---|---|---|
| transform | Applies CSS-like transformations to animated elements | transform: [{ rotate: rotation }, { scale: scaleValue }] |
| opacity | Controls the opacity of animated elements | opacity: opacityValue |
| backgroundColor | Changes the background color of animated elements | backgroundColor: colorValue |
Example: Basic useAnimatedStyle Usage
import { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
const opacity = useSharedValue(1);
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => {
return {
opacity: opacity.value,
transform: [{ scale: scale.value }],
};
});
// Apply animatedStyle to a component
<Animated.View style={animatedStyle} />
Example: Advanced useAnimatedStyle with Multiple Transforms
import { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
const rotation = useSharedValue(0);
const translateX = useSharedValue(0);
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{ rotate: `${rotation.value}deg` },
{ translateX: translateX.value },
{ scale: scale.value },
],
};
});
// Apply animatedStyle to a component
<Animated.View style={animatedStyle} />
4. Creating Worklets
Example: Basic Worklet Function
const myWorklet = Worklets.createRunTimeFn(() => {
'worklet';
return {
x: 100,
y: 200
};
});
| Property | Description | Usage |
|---|---|---|
| Worklets.createRunTimeFn | Creates a worklet function that runs on the UI thread | const fn = Worklets.createRunTimeFn(() => { ... }); |
| 'worklet' | Marker to indicate function runs on UI thread | 'worklet'; at the top of function body |
| return value | Object returned from worklet is accessible on JS thread | return { x: 100, y: 200 }; |
Note: Worklets must be created at module level or inside a component's render method, not inside event handlers.
5. Implementing withTiming Animation
| Property | Description | Values |
|---|---|---|
| duration | Duration of the animation in milliseconds | number |
| easing | Easing function to control animation curve | 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' |
| delay | Delay before starting the animation in milliseconds | number |
Example: Basic withTiming Usage
import { withTiming } from 'react-native-reanimated';
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{ translateX: withTiming(100, { duration: 500 }) }],
};
});
Example: withTiming with Easing
import { withTiming } from 'react-native-reanimated';
const animatedStyle = useAnimatedStyle(() => {
return {
opacity: withTiming(0.5, { easing: 'easeOut', duration: 300 }),
};
});
6. Implementing withSpring Animation
| Property | Description | Default Value | Notes |
|---|---|---|---|
| damping | Controls how much the spring resists oscillation | 10 |
Higher values = less oscillation |
| stiffness | How stiff the spring is | 100 |
Higher values = stiffer spring |
| mass | Mass of the animated object | 1 |
Affects how quickly the animation responds |
| overshootClamping | Whether to clamp overshoots | false |
Set to true to prevent overshooting |
| restDisplacementThreshold | Threshold for considering animation at rest | 0.01 |
Smaller values = more precise rest detection |
| restSpeedThreshold | Speed threshold to consider animation at rest | 0.01 |
Smaller values = more precise rest detection |
Example: withSpring Animation
import Animated, { withSpring } from 'react-native-reanimated';
const springConfig = {
damping: 10,
stiffness: 100,
mass: 1,
overshootClamping: false,
restDisplacementThreshold: 0.01,
restSpeedThreshold: 0.01,
};
const animatedValue = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{ translateX: withSpring(animatedValue.value, springConfig) }],
};
});
Note: The
withSpring animation is ideal for physics-based animations that mimic real-world motion.
7. Using withSequence and withRepeat
| Function | Description | Parameters | Example |
|---|---|---|---|
| withSequence | Runs animations in sequence | An array of animation functions | |
| withRepeat | Repeats an animation a specified number of times | Animation function, count (number), reverse (boolean) | |
Example: Combining withSequence and withRepeat
const animation = withRepeat(
withSequence(
timing(scale, { toValue: 1.2, duration: 300 }),
timing(scale, { toValue: 1, duration: 300 })
),
2
)
8. Using useAnimatedGestureHandler
| Property | Description | Values |
|---|---|---|
| onStart | Called when gesture starts | function |
| onActive | Called when gesture is active | function |
| onEnd | Called when gesture ends | function |
Example: Basic Gesture Handler
import { useAnimatedGestureHandler } from 'react-native-reanimated';
const gestureHandler = useAnimatedGestureHandler({
onStart: (event, context) => {
console.log('Gesture started');
},
onActive: (event, context) => {
console.log('Gesture active');
},
onEnd: (event, context) => {
console.log('Gesture ended');
},
});
9. Creating Animated Scrolling Effects
Example: Animated Scroll View with Reanimated
import React, { useRef } from 'react';
import { ScrollView, View, Text } from 'react-native';
import Animated, { useAnimatedScrollHandler, useAnimatedStyle } from 'react-native-reanimated';
const AnimatedScrollView = () => {
const scrollOffset = useRef(new Animated.Value(0)).current;
const scrollHandler = useAnimatedScrollHandler({
onScroll: (event) => {
scrollOffset.value = event.contentOffset.y;
}
});
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{ scale: 1 + scrollOffset.value * 0.001 }],
};
});
return (
<Animated.ScrollView
scrollEventThrottle={16}
onScroll={scrollHandler}
>
<Animated.View style={animatedStyle}>
<Text>Scroll to see animation</Text>
</Animated.View>
</Animated.ScrollView>
);
};
export default AnimatedScrollView;
| Property | Description | Values | Notes |
|---|---|---|---|
| scrollEventThrottle | How often scroll events are fired | 16 |
Recommended for smooth animations |
| onScroll | Callback for scroll events | function |
Used to update animated values |
| contentOffset.y | Vertical scroll position | number |
Used to drive animation properties |
Note: Use
scrollEventThrottle to control how frequently scroll events are processed for performance.
Warning: Avoid heavy computations in scroll handlers as they can cause jank.
10. Implementing Layout Animations
| Property | Description | Values |
|---|---|---|
| layoutAnimation | Enables layout animations for views | true or false |
| duration | Duration of the animation in milliseconds | number |
| easing | Easing function for the animation | 'easeIn' | 'easeOut' | 'easeInOut' |
Example: Basic Layout Animation
import { LayoutAnimation } from 'react-native';\n\nconst toggleLayout = () => {\n LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);\n};
Note: LayoutAnimation only works with native components and does not support all React Native components.
Warning: LayoutAnimation can cause performance issues if used excessively or with complex layouts.
11. Using Interpolate Function
| Property | Description | Values | Notes |
|---|---|---|---|
| interpolate | Maps input values to output values using a function | function(input, inputRange, outputRange) |
Used to create smooth transitions in animations |
Example: Interpolating Values
import { interpolate } from 'react-native-reanimated';
const progress = new Value(0);
const outputRange = [0, 100, 200];
const inputRange = [0, 0.5, 1];
const animatedValue = interpolate(progress, inputRange, outputRange);
Note: The
interpolate function is essential for creating complex animations that respond to user input or other dynamic values.
12. Optimizing Animation Performance
Example: Using useSharedValue for efficient state updates
import { useSharedValue, withTiming } from 'react-native-reanimated';
const AnimatedComponent = () => {
const opacity = useSharedValue(1);
const animateOpacity = () => {
opacity.value = withTiming(0, { duration: 500 });
};
return (
<Animated.View style={[styles.container, { opacity }]}>
<Text>Animated Text</Text>
</Animated.View>
);
};
| Optimization Technique | Description | Benefits |
|---|---|---|
| useSharedValue | Creates a shared value that can be accessed from both JS and native threads | Reduces overhead of passing values between JS and native layers |
| withTiming | Applies smooth timing to animations | Improves performance by leveraging native animation engine |
| useAnimatedStyle | Creates animated styles that update on every frame | Ensures consistent performance and avoids layout thrashing |
Note: Avoid using
useState or useEffect for animation values as they can cause unnecessary re-renders and performance drops.
Warning: Do not use
useState inside animation loops or frequent updates, as it can lead to performance degradation.