Using requestAnimationFrame for smooth animations in React Native
Posted in react-native-animations on January 14, 2025 by Hemanta Sapkota ‐ 6 min read
In this tutorial, you'll learn how to use requestAnimationFrame to create smooth animations in React Native. We'll cover the core logic, animation handling, and a performance comparison between different timing mechanisms.
Animation Preview
Custom Hooks for Animations
React Hooks are functions that allow you to “hook into” React state and lifecycle features from function components. They were introduced in React 16.8 to let you use state and other React features without writing a class component. Hooks make it easier to reuse stateful logic between components and make the code more readable by grouping related logic together. In the context of animations, we’ll create custom hooks that encapsulate all the animation logic, making it clean and reusable across our application.
Description of the hooks
Let’s examine the two custom hooks shown above and understand their key differences and similarities:
useCounter Hook
- Purpose: Implements a simple counting animation that increments a number smoothly
- Parameters: Takes
duration
andendValue
to control animation timing and final value - State Management: Uses a single state variable
counter
to track current value - Animation Logic: Linear increment based on elapsed time and target duration
- Output: Returns current counter value
useRotationAngle Hook
- Purpose: Creates a continuous rotating animation effect
- Parameters: Takes
speed
to control rotation velocity - State Management: Uses
rotationAngle
state to track current rotation degree - Animation Logic: Circular increment that resets at 360 degrees
- Output: Returns current rotation angle
Key Similarities
- Both hooks use
requestAnimationFrame
for smooth animations - Both implement cleanup using
cancelAnimationFrame
- Both use
useState
for managing animation state - Both are self-contained, reusable animation modules
Key Differences
Animation Type:
useCounter
: Linear, finite animation with start/end valuesuseRotationAngle
: Circular, infinite animation that loops
Parameters:
useCounter
: Focuses on duration and end stateuseRotationAngle
: Focuses on speed of rotation
Calculation Logic:
useCounter
: Uses timestamp-based progress calculationuseRotationAngle
: Uses simple increment with reset logic
Use Cases:
useCounter
: Best for progress indicators, loading statesuseRotationAngle
: Ideal for spinning animations, loading spinners
Animation Logic Explained
Let’s break down the core animation logic used in both hooks to understand how they achieve smooth animations:
useCounter Animation Logic
Initialization Phase
- Animation starts by capturing the initial timestamp
- Parameters define the target duration and final value
- Initial state is set to 0
Animation Frame Calculation
- Each frame calculates elapsed time since start
- Progress is normalized between 0 and 1
- Current value is interpolated linearly
Animation Loop Control
- requestAnimationFrame calls the next frame
- Loop continues while progress < 1
- Animation automatically stops at endValue
- Cleanup cancels any pending frames
useRotationAngle Animation Logic
Continuous Rotation Setup
- Initial angle starts at 0 degrees
- Speed parameter controls rotation velocity
- No end condition - runs indefinitely
Rotation Calculation
- Each frame increments angle by speed value
- Modulo operator keeps angle between 0-360
- Creates smooth circular motion
Performance Considerations
- Frame-based updates ensure smooth motion
- Automatic pausing when app is inactive
- Efficient memory management with cleanup
- Hardware acceleration friendly calculations
Why Use requestAnimationFrame for Animations?
Comparison with setTimeout and setInterval:
Feature | requestAnimationFrame | setTimeout / setInterval |
---|---|---|
Purpose | Designed for animations, syncs with screen refresh | General-purpose timers, not optimized for animation |
Performance | Smooth animations, low resource usage | Can cause jittery animations under load |
Accuracy | High (uses timestamps) | Affected by system delays |
Energy Efficiency | Pauses when tab is inactive | Wastes resources even when tab is inactive |
Ease of Use | Handles frame rate syncing automatically | Requires manual interval tuning |
When to Use Each
- Use
requestAnimationFrame
for animations like moving elements, fading, or scrolling effects. - Use
setTimeout / setInterval
for background tasks or non-visual periodic operations.
requestAnimationFrame vs Animation Libraries
Here’s a comparison between using requestAnimationFrame directly versus animation libraries:
Feature | requestAnimationFrame | Animation Libraries (Reanimated/Animated) |
---|---|---|
Learning Curve | Steeper - requires understanding animation loops and frame timing | Gentler - provides high-level declarative APIs |
Control | Full control over animation logic and timing | Less direct control, but easier to use pre-built animations |
Performance | Good performance when implemented correctly | Optimized out-of-the-box, runs on native thread |
Complexity | More boilerplate code needed | Simplified API reduces code complexity |
Flexibility | Can implement any custom animation logic | Limited to library’s built-in capabilities |
Debugging | Easier to debug (runs in JS thread) | Can be harder to debug (especially native thread issues) |
When to Choose Each
Use requestAnimationFrame when:
- You need complete control over animation logic
- Implementing custom, complex animations
- Building performance-critical animations from scratch
- Learning animation fundamentals
Use Animation Libraries when:
- Building common UI animations quickly
- Need cross-platform consistency
- Want gesture-based animations
- Prefer declarative animation syntax
Conclusion
In this tutorial, we’ve explored how to use requestAnimationFrame
for smooth animations in React Native. We’ve created two custom hooks, useCounter
and useRotationAngle
, to demonstrate how to implement animations using this method. We’ve also compared requestAnimationFrame
with setTimeout
and setInterval
to understand the key differences and when to use each.
By leveraging requestAnimationFrame
, you can create high-performance animations that are both smooth and energy-efficient, providing a better user experience.