Using requestAnimationFrame for smooth animations in React Native

Posted in react-native-animations on January 14, 2025 by Hemanta Sapkota ‐ 6 min read

Using requestAnimationFrame for smooth animations in React Native

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 and endValue 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

  1. Both hooks use requestAnimationFrame for smooth animations
  2. Both implement cleanup using cancelAnimationFrame
  3. Both use useState for managing animation state
  4. Both are self-contained, reusable animation modules

Key Differences

  1. Animation Type:

    • useCounter: Linear, finite animation with start/end values
    • useRotationAngle: Circular, infinite animation that loops
  2. Parameters:

    • useCounter: Focuses on duration and end state
    • useRotationAngle: Focuses on speed of rotation
  3. Calculation Logic:

    • useCounter: Uses timestamp-based progress calculation
    • useRotationAngle: Uses simple increment with reset logic
  4. Use Cases:

    • useCounter: Best for progress indicators, loading states
    • useRotationAngle: 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

  1. Initialization Phase

    • Animation starts by capturing the initial timestamp
    • Parameters define the target duration and final value
    • Initial state is set to 0
  2. Animation Frame Calculation

    • Each frame calculates elapsed time since start
    • Progress is normalized between 0 and 1
    • Current value is interpolated linearly
  3. 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

  1. Continuous Rotation Setup

    • Initial angle starts at 0 degrees
    • Speed parameter controls rotation velocity
    • No end condition - runs indefinitely
  2. Rotation Calculation

    • Each frame increments angle by speed value
    • Modulo operator keeps angle between 0-360
    • Creates smooth circular motion
  3. 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:

FeaturerequestAnimationFramesetTimeout / setInterval
PurposeDesigned for animations, syncs with screen refreshGeneral-purpose timers, not optimized for animation
PerformanceSmooth animations, low resource usageCan cause jittery animations under load
AccuracyHigh (uses timestamps)Affected by system delays
Energy EfficiencyPauses when tab is inactiveWastes resources even when tab is inactive
Ease of UseHandles frame rate syncing automaticallyRequires 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:

FeaturerequestAnimationFrameAnimation Libraries (Reanimated/Animated)
Learning CurveSteeper - requires understanding animation loops and frame timingGentler - provides high-level declarative APIs
ControlFull control over animation logic and timingLess direct control, but easier to use pre-built animations
PerformanceGood performance when implemented correctlyOptimized out-of-the-box, runs on native thread
ComplexityMore boilerplate code neededSimplified API reduces code complexity
FlexibilityCan implement any custom animation logicLimited to library’s built-in capabilities
DebuggingEasier 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.

comments powered by Disqus